From c3c879f2c63afbb39ad4d76ecc083cddd41d9946 Mon Sep 17 00:00:00 2001 From: Takayuki Shimizukawa Date: Tue, 29 Apr 2014 19:59:58 +0900 Subject: [PATCH] use six privided functions/classes to support py2/py3 in one source. refs #1350. --- sphinx/builders/html.py | 7 ++++--- sphinx/builders/linkcheck.py | 6 +++--- sphinx/builders/manpage.py | 4 ++-- sphinx/config.py | 2 +- sphinx/directives/other.py | 3 ++- sphinx/environment.py | 6 +++--- sphinx/ext/coverage.py | 3 ++- sphinx/ext/napoleon/docstring.py | 12 ++++-------- sphinx/jinja2glue.py | 3 ++- sphinx/locale/__init__.py | 4 ++-- sphinx/quickstart.py | 10 +++------- sphinx/search/__init__.py | 7 ++++--- sphinx/theming.py | 14 ++++++++------ sphinx/util/__init__.py | 3 ++- sphinx/util/jsdump.py | 6 ++++-- sphinx/util/jsonimpl.py | 5 +++-- sphinx/versioning.py | 6 +++--- sphinx/websupport/__init__.py | 3 +-- sphinx/writers/html.py | 3 ++- sphinx/writers/texinfo.py | 4 ++-- tests/coverage.py | 10 +++------- tests/etree13/ElementTree.py | 5 ++++- tests/test_intl.py | 2 +- tests/test_quickstart.py | 31 ++++++++++++++----------------- 24 files changed, 79 insertions(+), 80 deletions(-) diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index 035c734ce..4ecde7f9b 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 +import six +from six.moves import cPickle as pickle from docutils import nodes from docutils.io import DocTreeInput, StringOutput from docutils.core import Publisher @@ -295,7 +296,7 @@ class StandaloneHTMLBuilder(Builder): if favicon and os.path.splitext(favicon)[1] != '.ico': self.warn('html_favicon is not an .ico file') - if not isinstance(self.config.html_use_opensearch, basestring): + if not isinstance(self.config.html_use_opensearch, six.string_types): self.warn('html_use_opensearch config value must now be a string') self.relations = self.env.collect_relations() @@ -713,7 +714,7 @@ class StandaloneHTMLBuilder(Builder): if sidebars is None: # keep defaults pass - elif isinstance(sidebars, basestring): + elif isinstance(sidebars, six.string_types): # 0.x compatible mode: insert custom sidebar before searchbox customsidebar = sidebars sidebars = None diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index e46c8379f..8c0f5040d 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -10,7 +10,6 @@ """ import re -import Queue import socket import threading from os import path @@ -18,6 +17,7 @@ from urllib2 import build_opener, unquote, Request, \ HTTPError, HTTPRedirectHandler from HTMLParser import HTMLParser, HTMLParseError +from six.moves import queue from docutils import nodes from sphinx.builders import Builder @@ -98,8 +98,8 @@ class CheckExternalLinksBuilder(Builder): open(path.join(self.outdir, 'output.txt'), 'w').close() # create queues and worker threads - self.wqueue = Queue.Queue() - self.rqueue = Queue.Queue() + self.wqueue = queue.Queue() + self.rqueue = queue.Queue() self.workers = [] for i in range(self.app.config.linkcheck_workers): thread = threading.Thread(target=self.check_thread) diff --git a/sphinx/builders/manpage.py b/sphinx/builders/manpage.py index 4b360cde0..29598615a 100644 --- a/sphinx/builders/manpage.py +++ b/sphinx/builders/manpage.py @@ -11,11 +11,11 @@ from os import path +import six 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, six.string_types): if authors: authors = [authors] else: diff --git a/sphinx/config.py b/sphinx/config.py index 6cbbd6410..40c1b27e5 100644 --- a/sphinx/config.py +++ b/sphinx/config.py @@ -269,7 +269,7 @@ class Config(object): continue elif isinstance(defvalue, list): config[valname] = value.split(',') - elif isinstance(defvalue, (int, long)): + elif isinstance(defvalue, six.integer_types): try: config[valname] = int(value) except ValueError: diff --git a/sphinx/directives/other.py b/sphinx/directives/other.py index d28c00fb5..01c8c012a 100644 --- a/sphinx/directives/other.py +++ b/sphinx/directives/other.py @@ -7,6 +7,7 @@ :license: BSD, see LICENSE for details. """ +from six.moves import range from docutils import nodes from docutils.parsers.rst import Directive, directives from docutils.parsers.rst.directives.admonitions import BaseAdmonition @@ -368,7 +369,7 @@ class Only(Directive): # be placed in the doctree. n_sects_to_raise = current_depth - nested_depth + 1 parent = self.state.parent - for i in xrange(n_sects_to_raise): + for i in range(n_sects_to_raise): if parent.parent: parent = parent.parent parent.append(node) diff --git a/sphinx/environment.py b/sphinx/environment.py index 195ae724b..c9d425bec 100644 --- a/sphinx/environment.py +++ b/sphinx/environment.py @@ -18,12 +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 import six +from six.moves import cPickle as pickle, zip from docutils import nodes from docutils.io import FileInput, NullOutput from docutils.core import Publisher @@ -1649,7 +1649,7 @@ class BuildEnvironment: # else it will stay None # same for children if includes: - for subindex, args in enumerate(izip(includes, + for subindex, args in enumerate(zip(includes, [None] + includes, includes[1:] + [None])): collect([(docname, subindex)] + parents, diff --git a/sphinx/ext/coverage.py b/sphinx/ext/coverage.py index f1ac6cec5..24477b426 100644 --- a/sphinx/ext/coverage.py +++ b/sphinx/ext/coverage.py @@ -13,9 +13,10 @@ import re import glob import inspect -import cPickle as pickle from os import path +from six.moves import cPickle as pickle + from sphinx.builders import Builder diff --git a/sphinx/ext/napoleon/docstring.py b/sphinx/ext/napoleon/docstring.py index dea55c629..3e98cc9f0 100644 --- a/sphinx/ext/napoleon/docstring.py +++ b/sphinx/ext/napoleon/docstring.py @@ -16,15 +16,11 @@ import inspect import re import six +from six.moves import range from sphinx.ext.napoleon.iterators import modify_iter -if six.PY3: - basestring = str - xrange = range - - _directive_regex = re.compile(r'\.\. \S+::') _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*(.*)') @@ -118,7 +114,7 @@ class GoogleDocstring(object): self._name = name self._obj = obj self._opt = options - if isinstance(docstring, basestring): + if isinstance(docstring, six.string_types): docstring = docstring.splitlines() self._lines = docstring self._line_iter = modify_iter(docstring, modifier=lambda s: s.rstrip()) @@ -599,7 +595,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 @@ -747,7 +743,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, six.string_types): pattern = r'[=\-`:\'"~^_*+#<>]{' + str(len(section)) + r'}$' return bool(re.match(pattern, underline)) elif self._directive_sections: diff --git a/sphinx/jinja2glue.py b/sphinx/jinja2glue.py index f4a5a8159..d2cad6e37 100644 --- a/sphinx/jinja2glue.py +++ b/sphinx/jinja2glue.py @@ -12,6 +12,7 @@ from os import path from pprint import pformat +import six 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, six.string_types): return val.lower() in ('true', '1', 'yes', 'on') return bool(val) diff --git a/sphinx/locale/__init__.py b/sphinx/locale/__init__.py index fc2ffedb6..913533f48 100644 --- a/sphinx/locale/__init__.py +++ b/sphinx/locale/__init__.py @@ -10,12 +10,12 @@ """ import gettext -import UserString import six +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. diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index 180066e00..f2ccb4e50 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -16,8 +16,6 @@ from io import open TERM_ENCODING = getattr(sys.stdin, 'encoding', None) -import six - #try to import readline, unix specific enhancement try: import readline @@ -28,6 +26,8 @@ try: except ImportError: pass +import six +from six.moves import input from docutils.utils import column_width from sphinx import __version__ @@ -37,11 +37,7 @@ 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 = '> ' diff --git a/sphinx/search/__init__.py b/sphinx/search/__init__.py index b4f5a799e..93eadf80a 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 +import six +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, six.string_types): format = self.formats[format] frozen = format.load(stream) # if an old index is present, we treat it as not existing. @@ -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, six.string_types): format = self.formats[format] format.dump(self.freeze(), stream) diff --git a/sphinx/theming.py b/sphinx/theming.py index abc09c17f..d0435db78 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 +import six +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,7 +143,7 @@ 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(): if option not in options: @@ -188,7 +190,7 @@ def load_theme_plugins(): except: path = func_or_path - if isinstance(path, basestring): + if isinstance(path, six.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 3c9366a17..2330f42fd 100644 --- a/sphinx/util/__init__.py +++ b/sphinx/util/__init__.py @@ -22,6 +22,7 @@ from codecs import open, BOM_UTF8 from collections import deque import six +from six.moves import range import docutils from docutils.utils import relative_path @@ -327,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 diff --git a/sphinx/util/jsdump.py b/sphinx/util/jsdump.py index 85845a722..709439a6a 100644 --- a/sphinx/util/jsdump.py +++ b/sphinx/util/jsdump.py @@ -12,6 +12,8 @@ import re +import six + 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, six.string_types): obj = str(obj) if _nameonly_re.match(obj) and obj not in reswords: return obj # return it as a bare word @@ -93,7 +95,7 @@ def dumps(obj, key=False): ) for key, value in obj.iteritems()) elif isinstance(obj, (tuple, list, set)): return '[%s]' % ','.join(dumps(x) for x in obj) - elif isinstance(obj, basestring): + elif isinstance(obj, six.string_types): return encode_string(obj) raise TypeError(type(obj)) diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py index 05a6ec6e2..6682a3765 100644 --- a/sphinx/util/jsonimpl.py +++ b/sphinx/util/jsonimpl.py @@ -9,14 +9,15 @@ :license: BSD, see LICENSE for details. """ -import UserString import json +from six.moves import UserString + class SphinxJSONEncoder(json.JSONEncoder): """JSONEncoder subclass that forces translation proxies.""" def default(self, obj): - if isinstance(obj, UserString.UserString): + if isinstance(obj, UserString): return unicode(obj) return json.JSONEncoder.default(self, obj) diff --git a/sphinx/versioning.py b/sphinx/versioning.py index 8cc618e8d..45bb041b3 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 -import six +from six.moves import range, zip_longest # 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 six.moves.zip_longest(old_iter, new_iter): + for old_node, new_node in zip_longest(old_iter, new_iter): if old_node is None: new_nodes.append(new_node) continue @@ -116,7 +116,7 @@ def levenshtein_distance(a, b): a, b = b, a if not a: return len(b) - previous_row = xrange(len(b) + 1) + previous_row = range(len(b) + 1) for i, column1 in enumerate(a): current_row = [i + 1] for j, column2 in enumerate(b): diff --git a/sphinx/websupport/__init__.py b/sphinx/websupport/__init__.py index 0e9131d0e..4cdedc0dd 100644 --- a/sphinx/websupport/__init__.py +++ b/sphinx/websupport/__init__.py @@ -10,12 +10,11 @@ """ import sys -import cPickle as pickle import posixpath from os import path +from six.moves import cPickle as pickle from jinja2 import Environment, FileSystemLoader - from docutils.core import publish_parts from sphinx.application import Sphinx diff --git a/sphinx/writers/html.py b/sphinx/writers/html.py index 13dd5d424..6871357d7 100644 --- a/sphinx/writers/html.py +++ b/sphinx/writers/html.py @@ -14,6 +14,7 @@ import posixpath import os import copy +import six 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, six.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/texinfo.py b/sphinx/writers/texinfo.py index 76f28a4ff..b770fabc0 100644 --- a/sphinx/writers/texinfo.py +++ b/sphinx/writers/texinfo.py @@ -10,10 +10,10 @@ """ import re -import string import textwrap from os import path +from six.moves import range from docutils import nodes, writers from sphinx import addnodes, __version__ @@ -974,7 +974,7 @@ class TexinfoTranslator(nodes.NodeVisitor): self.body.append('\n%s\n' % self.entry_sep) self.entry_sep = '@tab' def depart_entry(self, node): - for i in xrange(node.get('morecols', 0)): + for i in range(node.get('morecols', 0)): self.body.append('\n@tab\n') ## Field Lists diff --git a/tests/coverage.py b/tests/coverage.py index 95063b676..89b81e5df 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 +import six + # 2. IMPLEMENTATION # @@ -845,7 +841,7 @@ class coverage: # On windows, the shell doesn't expand wildcards. Do it here. globbed = [] for morf in morfs: - if isinstance(morf, strclass): + if isinstance(morf, six.string_types): globbed.extend(glob.glob(morf)) else: globbed.append(morf) diff --git a/tests/etree13/ElementTree.py b/tests/etree13/ElementTree.py index 892b08a01..3163d3efb 100644 --- a/tests/etree13/ElementTree.py +++ b/tests/etree13/ElementTree.py @@ -81,6 +81,9 @@ from __future__ import generators from __future__ import absolute_import +import six + + __all__ = [ # public symbols "Comment", @@ -828,7 +831,7 @@ def _namespaces(elem, encoding, default_namespace=None): tag = elem.tag if isinstance(tag, QName) and tag.text not in qnames: add_qname(tag.text) - elif isinstance(tag, basestring): + elif isinstance(tag, six.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: diff --git a/tests/test_intl.py b/tests/test_intl.py index 64f584fbb..3f25050c5 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -77,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, six.string_types) and tag is not None: return if self.text: yield self.text diff --git a/tests/test_quickstart.py b/tests/test_quickstart.py index f729f570f..6c1ffcf8a 100644 --- a/tests/test_quickstart.py +++ b/tests/test_quickstart.py @@ -14,7 +14,7 @@ import time import six -from util import raises, with_tempdir, with_app, SkipTest +from util import raises, with_tempdir, SkipTest from sphinx import application from sphinx import quickstart as qs @@ -28,9 +28,9 @@ warnfile = six.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) @@ -47,15 +47,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 = six.moves.input def teardown_module(): - qs.term_input = real_raw_input + qs.term_input = real_input qs.TERM_ENCODING = getattr(sys.stdin, 'encoding', None) coloron() @@ -68,7 +65,7 @@ def test_quickstart_inputstrip(): 'Q3': 'N', 'Q4': 'N ', } - qs.term_input = mock_raw_input(answers) + qs.term_input = mock_input(answers) qs.do_prompt(d, 'k1', 'Q1') assert d['k1'] == 'Y' qs.do_prompt(d, 'k2', 'Q2') @@ -88,7 +85,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 +110,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 +128,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 +183,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 +229,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 +250,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 +276,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)