From a8fc938d1b9fb1be7979da8b8236aba287fc082e Mon Sep 17 00:00:00 2001 From: Takayuki Shimizukawa Date: Sun, 15 Dec 2013 14:16:53 +0900 Subject: [PATCH 1/2] Drop python-2.5 and remove 2.4,2.5 support codes --- CHANGES | 6 ++ doc/install.rst | 6 +- doc/intro.rst | 2 +- setup.py | 12 +-- sphinx/__init__.py | 4 +- sphinx/builders/epub.py | 8 -- sphinx/builders/html.py | 12 +-- sphinx/builders/linkcheck.py | 3 +- sphinx/ext/autodoc.py | 4 +- sphinx/highlighting.py | 12 +-- sphinx/pycode/__init__.py | 2 +- sphinx/pycode/pgen2/parse.c | 89 ----------------- sphinx/quickstart.py | 2 +- sphinx/transforms.py | 1 - sphinx/util/inspect.py | 9 +- sphinx/util/jsonimpl.py | 18 +--- sphinx/util/osutil.py | 10 +- sphinx/util/pycompat.py | 184 ++--------------------------------- sphinx/versioning.py | 3 +- sphinx/writers/latex.py | 1 - tests/test_autodoc.py | 11 +-- tests/test_intl.py | 6 +- tests/test_versioning.py | 1 - tests/test_websupport.py | 7 +- tests/util.py | 7 +- tox.ini | 10 +- 26 files changed, 54 insertions(+), 376 deletions(-) diff --git a/CHANGES b/CHANGES index c15cd0b93..3b6c88881 100644 --- a/CHANGES +++ b/CHANGES @@ -1,6 +1,12 @@ Release 1.3 (in development) ============================ +Change support versions +----------------------- + +* Drop Python-2.5. (support code was completely removed) + + Release 1.2 (released Dec 10, 2013) =================================== diff --git a/doc/install.rst b/doc/install.rst index 9c2584208..828dc3b43 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -4,7 +4,7 @@ Installing Sphinx ================= Since Sphinx is written in the Python language, you need to install Python -(the required version is at least 2.5) and Sphinx. +(the required version is at least 2.6) and Sphinx. Sphinx packages are available on the `Python Package Index `_. @@ -79,8 +79,8 @@ sidebar and under "Quick Links", click "Windows Installer" to download. .. note:: - Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.2 can run - under Python 2.5 to 2.7 and 3.1 to 3.3, with the recommended version being + Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.3 can run + under Python 2.6, 2.7 and 3.1 to 3.3, with the recommended version being 2.7. This chapter assumes you have installed Python 2.7. Follow the Windows installer for Python. diff --git a/doc/intro.rst b/doc/intro.rst index 4d052c818..f0593cee2 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -50,7 +50,7 @@ See the :ref:`pertinent section in the FAQ list `. Prerequisites ------------- -Sphinx needs at least **Python 2.5** or **Python 3.1** to run, as well as the +Sphinx needs at least **Python 2.6** or **Python 3.1** to run, as well as the docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.7 or some (not broken) SVN trunk snapshot. If you like to have source code highlighting support, you must also install the Pygments_ library. diff --git a/setup.py b/setup.py index 553cf12d2..543a319d2 100644 --- a/setup.py +++ b/setup.py @@ -44,20 +44,20 @@ A development egg can be found `here `_. ''' +if sys.version_info < (2, 6): + print('ERROR: Sphinx requires at least Python 2.6 to run.') + sys.exit(1) + requires = ['Pygments>=1.2', 'docutils>=0.7'] if sys.version_info[:3] >= (3, 3, 0): requires[1] = 'docutils>=0.10' -if sys.version_info < (2, 6) or (3, 0) <= sys.version_info < (3, 3): +if (3, 0) <= sys.version_info < (3, 3): requires.append('Jinja2>=2.3,<2.7') -else: +else: # 2.6, 2.7, 3.3 or later requires.append('Jinja2>=2.3') -if sys.version_info < (2, 5): - print('ERROR: Sphinx requires at least Python 2.5 to run.') - sys.exit(1) - # tell distribute to use 2to3 with our own fixers extra = {} if sys.version_info >= (3, 0): diff --git a/sphinx/__init__.py b/sphinx/__init__.py index f93e57a11..bbd45b245 100644 --- a/sphinx/__init__.py +++ b/sphinx/__init__.py @@ -42,8 +42,8 @@ if '+' in __version__ or 'pre' in __version__: def main(argv=sys.argv): """Sphinx build "main" command-line entry.""" - if sys.version_info[:3] < (2, 5, 0): - sys.stderr.write('Error: Sphinx requires at least Python 2.5 to run.\n') + if sys.version_info[:3] < (2, 6, 0): + sys.stderr.write('Error: Sphinx requires at least Python 2.6 to run.\n') return 1 try: from sphinx import cmdline diff --git a/sphinx/builders/epub.py b/sphinx/builders/epub.py index 1dfcc7045..35061b79c 100644 --- a/sphinx/builders/epub.py +++ b/sphinx/builders/epub.py @@ -12,7 +12,6 @@ import os import re -import sys import time import codecs import zipfile @@ -750,12 +749,5 @@ class EpubBuilder(StandaloneHTMLBuilder): zipfile.ZIP_STORED) for file in projectfiles: fp = path.join(outdir, file) - if sys.version_info < (2, 6): - # When zipile.ZipFile.write call with unicode filename, ZipFile - # encode filename to 'utf-8' (only after Python-2.6). - if isinstance(file, unicode): - # OEBPS Container Format (OCF) 2.0.1 specification require - # "File Names MUST be UTF-8 encoded". - file = file.encode('utf-8') epub.write(fp, file, zipfile.ZIP_DEFLATED) epub.close() diff --git a/sphinx/builders/html.py b/sphinx/builders/html.py index e00b91c36..b0cde2976 100644 --- a/sphinx/builders/html.py +++ b/sphinx/builders/html.py @@ -16,11 +16,7 @@ import codecs import posixpath import cPickle as pickle from os import path -try: - from hashlib import md5 -except ImportError: - # 2.4 compatibility - from md5 import md5 +from hashlib import md5 from docutils import nodes from docutils.io import DocTreeInput, StringOutput @@ -35,7 +31,7 @@ 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 any, b +from sphinx.util.pycompat import b from sphinx.errors import SphinxError from sphinx.locale import _ from sphinx.search import js_index @@ -1095,8 +1091,4 @@ class JSONHTMLBuilder(SerializingHTMLBuilder): searchindex_filename = 'searchindex.json' def init(self): - if jsonimpl.json is None: - raise SphinxError( - 'The module simplejson (or json in Python >= 2.6) ' - 'is not available. The JSONHTMLBuilder builder will not work.') SerializingHTMLBuilder.init(self) diff --git a/sphinx/builders/linkcheck.py b/sphinx/builders/linkcheck.py index c567401c5..c3369b5af 100644 --- a/sphinx/builders/linkcheck.py +++ b/sphinx/builders/linkcheck.py @@ -10,7 +10,6 @@ """ import re -import sys import Queue import socket import threading @@ -97,7 +96,7 @@ class CheckExternalLinksBuilder(Builder): def check_thread(self): kwargs = {} - if sys.version_info > (2, 5) and self.app.config.linkcheck_timeout: + if self.app.config.linkcheck_timeout: kwargs['timeout'] = self.app.config.linkcheck_timeout def check(): diff --git a/sphinx/ext/autodoc.py b/sphinx/ext/autodoc.py index 8d78feb21..5ea64bf30 100644 --- a/sphinx/ext/autodoc.py +++ b/sphinx/ext/autodoc.py @@ -29,7 +29,7 @@ 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 base_exception, class_types +from sphinx.util.pycompat import class_types from sphinx.util.docstrings import prepare_docstring @@ -1128,7 +1128,7 @@ class ExceptionDocumenter(ClassDocumenter): @classmethod def can_document_member(cls, member, membername, isattr, parent): return isinstance(member, class_types) and \ - issubclass(member, base_exception) + issubclass(member, BaseException) class DataDocumenter(ModuleLevelDocumenter): diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index df422321b..7a3927d31 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -63,12 +63,6 @@ _LATEX_STYLES = r''' \newcommand\PYGZcb{\char`\}} ''' -parsing_exceptions = (SyntaxError, UnicodeEncodeError) -if sys.version_info < (2, 5): - # Python <= 2.4 raises MemoryError when parsing an - # invalid encoding cookie - parsing_exceptions += MemoryError, - class PygmentsBridge(object): # Set these attributes if you want to have different Pygments formatters @@ -131,10 +125,6 @@ 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 we're using 2.5, use the with statement - if sys.version_info >= (2, 5): - src = 'from __future__ import with_statement\n' + src - if sys.version_info < (3, 0) and isinstance(src, unicode): # Non-ASCII chars will only occur in string literals # and comments. If we wanted to give them to the parser @@ -154,7 +144,7 @@ class PygmentsBridge(object): try: parser.suite(src) - except parsing_exceptions: + except (SyntaxError, UnicodeEncodeError): return False else: return True diff --git a/sphinx/pycode/__init__.py b/sphinx/pycode/__init__.py index 64999df88..d69fe0ca4 100644 --- a/sphinx/pycode/__init__.py +++ b/sphinx/pycode/__init__.py @@ -16,7 +16,7 @@ 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 next, StringIO, BytesIO, TextIOWrapper +from sphinx.util.pycompat import StringIO, BytesIO, TextIOWrapper from sphinx.util.docstrings import prepare_docstring, prepare_commentdoc diff --git a/sphinx/pycode/pgen2/parse.c b/sphinx/pycode/pgen2/parse.c index e09f50589..96fa6c8b2 100644 --- a/sphinx/pycode/pgen2/parse.c +++ b/sphinx/pycode/pgen2/parse.c @@ -353,95 +353,6 @@ static void __Pyx_RaiseArgtupleInvalid(const char* func_name, int exact, static int __Pyx_ParseOptionalKeywords(PyObject *kwds, PyObject **argnames[], PyObject *kwds2, PyObject *values[], Py_ssize_t num_pos_args, const char* function_name); /*proto*/ -#if PY_VERSION_HEX < 0x02050000 -#ifndef PyAnySet_CheckExact - -#define PyAnySet_CheckExact(ob) \ - ((ob)->ob_type == &PySet_Type || \ - (ob)->ob_type == &PyFrozenSet_Type) - -#define PySet_New(iterable) \ - PyObject_CallFunctionObjArgs((PyObject *)&PySet_Type, (iterable), NULL) - -#define Pyx_PyFrozenSet_New(iterable) \ - PyObject_CallFunctionObjArgs((PyObject *)&PyFrozenSet_Type, (iterable), NULL) - -#define PySet_Size(anyset) \ - PyObject_Size((anyset)) - -#define PySet_Contains(anyset, key) \ - PySequence_Contains((anyset), (key)) - -#define PySet_Pop(set) \ - PyObject_CallMethod(set, (char *)"pop", NULL) - -static INLINE int PySet_Clear(PyObject *set) { - PyObject *ret = PyObject_CallMethod(set, (char *)"clear", NULL); - if (!ret) return -1; - Py_DECREF(ret); return 0; -} - -static INLINE int PySet_Discard(PyObject *set, PyObject *key) { - PyObject *ret = PyObject_CallMethod(set, (char *)"discard", (char *)"O", key); - if (!ret) return -1; - Py_DECREF(ret); return 0; -} - -static INLINE int PySet_Add(PyObject *set, PyObject *key) { - PyObject *ret = PyObject_CallMethod(set, (char *)"add", (char *)"O", key); - if (!ret) return -1; - Py_DECREF(ret); return 0; -} - -#endif /* PyAnySet_CheckExact (<= Py2.4) */ - -#if PY_VERSION_HEX < 0x02040000 -#ifndef Py_SETOBJECT_H -#define Py_SETOBJECT_H - -static PyTypeObject *__Pyx_PySet_Type = NULL; -static PyTypeObject *__Pyx_PyFrozenSet_Type = NULL; - -#define PySet_Type (*__Pyx_PySet_Type) -#define PyFrozenSet_Type (*__Pyx_PyFrozenSet_Type) - -#define PyAnySet_Check(ob) \ - (PyAnySet_CheckExact(ob) || \ - PyType_IsSubtype((ob)->ob_type, &PySet_Type) || \ - PyType_IsSubtype((ob)->ob_type, &PyFrozenSet_Type)) - -#define PyFrozenSet_CheckExact(ob) ((ob)->ob_type == &PyFrozenSet_Type) - -static int __Pyx_Py23SetsImport(void) { - PyObject *sets=0, *Set=0, *ImmutableSet=0; - - sets = PyImport_ImportModule((char *)"sets"); - if (!sets) goto bad; - Set = PyObject_GetAttrString(sets, (char *)"Set"); - if (!Set) goto bad; - ImmutableSet = PyObject_GetAttrString(sets, (char *)"ImmutableSet"); - if (!ImmutableSet) goto bad; - Py_DECREF(sets); - - __Pyx_PySet_Type = (PyTypeObject*) Set; - __Pyx_PyFrozenSet_Type = (PyTypeObject*) ImmutableSet; - - return 0; - - bad: - Py_XDECREF(sets); - Py_XDECREF(Set); - Py_XDECREF(ImmutableSet); - return -1; -} - -#else -static int __Pyx_Py23SetsImport(void) { return 0; } -#endif /* !Py_SETOBJECT_H */ -#endif /* < Py2.4 */ -#endif /* < Py2.5 */ - - static INLINE PyObject *__Pyx_GetItemInt_Generic(PyObject *o, PyObject* j) { PyObject *r; if (!j) return NULL; diff --git a/sphinx/quickstart.py b/sphinx/quickstart.py index a4dca3333..5733b34b5 100644 --- a/sphinx/quickstart.py +++ b/sphinx/quickstart.py @@ -11,6 +11,7 @@ import sys, os, time, re from os import path +from io import open TERM_ENCODING = getattr(sys.stdin, 'encoding', None) @@ -21,7 +22,6 @@ from sphinx.util.osutil import make_filename from sphinx.util.console import purple, bold, red, turquoise, \ nocolor, color_terminal from sphinx.util import texescape -from sphinx.util.pycompat import open # function to get input from terminal -- overridden by the test suite try: diff --git a/sphinx/transforms.py b/sphinx/transforms.py index 338d47392..35e9d297b 100644 --- a/sphinx/transforms.py +++ b/sphinx/transforms.py @@ -23,7 +23,6 @@ from sphinx.util import split_index_msg from sphinx.util.nodes import traverse_translatable_index, extract_messages from sphinx.util.osutil import ustrftime, find_catalog from sphinx.util.compat import docutils_version -from sphinx.util.pycompat import all from sphinx.domains.std import ( make_term_from_paragraph_node, make_termnodes_from_paragraph_node, diff --git a/sphinx/util/inspect.py b/sphinx/util/inspect.py index 61061a9af..c7556d056 100644 --- a/sphinx/util/inspect.py +++ b/sphinx/util/inspect.py @@ -55,7 +55,7 @@ if sys.version_info >= (3, 0): raise TypeError('%r is not a Python function' % func) return inspect.getfullargspec(func) -elif sys.version_info >= (2, 5): +else: # 2.6, 2.7 from functools import partial def getargspec(func): """Like inspect.getargspec but supports functools.partial as well.""" @@ -86,12 +86,7 @@ elif sys.version_info >= (2, 5): del func_defaults[i] except IndexError: pass - if sys.version_info >= (2, 6): - return inspect.ArgSpec(args, varargs, varkw, func_defaults) - else: - return (args, varargs, varkw, func_defaults) -else: - getargspec = inspect.getargspec + return inspect.ArgSpec(args, varargs, varkw, func_defaults) def isdescriptor(x): diff --git a/sphinx/util/jsonimpl.py b/sphinx/util/jsonimpl.py index aa0ea8251..de846b240 100644 --- a/sphinx/util/jsonimpl.py +++ b/sphinx/util/jsonimpl.py @@ -10,27 +10,15 @@ """ import UserString - -try: - import json - # json-py's json module has no JSONEncoder; this will raise AttributeError - # if json-py is imported instead of the built-in json module - JSONEncoder = json.JSONEncoder -except (ImportError, AttributeError): - try: - import simplejson as json - JSONEncoder = json.JSONEncoder - except ImportError: - json = None - JSONEncoder = object +import json -class SphinxJSONEncoder(JSONEncoder): +class SphinxJSONEncoder(json.JSONEncoder): """JSONEncoder subclass that forces translation proxies.""" def default(self, obj): if isinstance(obj, UserString.UserString): return unicode(obj) - return JSONEncoder.default(self, obj) + return json.JSONEncoder.default(self, obj) def dump(obj, fp, *args, **kwds): diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py index 87717771a..e8655fe1f 100644 --- a/sphinx/util/osutil.py +++ b/sphinx/util/osutil.py @@ -69,6 +69,10 @@ def ensuredir(path): raise +# TODO: This function can be removed because this function is same as os.walk +# of Python2.6, 2.7, 3.1, 3.2, 3.3. +# HOWEVER, this function is customized to check UnicodeError that obstacle to +# replace the function with the os.walk. def walk(top, topdown=True, followlinks=False): """Backport of os.walk from 2.6, where the *followlinks* argument was added. @@ -155,9 +159,8 @@ else: def safe_relpath(path, start=None): - from sphinx.util.pycompat import relpath try: - return relpath(path, start) + return os.path.relpath(path, start) except ValueError: return path @@ -171,14 +174,13 @@ def find_catalog(docname, compaction): def find_catalog_files(docname, srcdir, locale_dirs, lang, compaction): - from sphinx.util.pycompat import relpath if not(lang and locale_dirs): return [] domain = find_catalog(docname, compaction) files = [gettext.find(domain, path.join(srcdir, dir_), [lang]) for dir_ in locale_dirs] - files = [relpath(f, srcdir) for f in files if f] + files = [path.relpath(f, srcdir) for f in files if f] return files diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py index 3d252c917..68e6d8fbc 100644 --- a/sphinx/util/pycompat.py +++ b/sphinx/util/pycompat.py @@ -11,7 +11,6 @@ import sys import codecs -import encodings # ------------------------------------------------------------------------------ # Python 2/3 compatibility @@ -45,6 +44,7 @@ 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 else: # Python 2 @@ -62,6 +62,7 @@ else: # safely encode a string for printing to the terminal def terminal_safe(s): return s.encode('ascii', 'backslashreplace') + from itertools import izip_longest as zip_longest # use Python 3 name def execfile_(filepath, _globals): @@ -74,8 +75,8 @@ def execfile_(filepath, _globals): finally: f.close() - # py25,py26,py31 accept only LF eol instead of CRLF - if sys.version_info[:2] in ((2, 5), (2, 6), (3, 1)): + # py26,py31 accept only LF eol instead of CRLF + if sys.version_info[:2] in ((2, 6), (3, 1)): source = source.replace(b('\r\n'), b('\n')) # compile to a code object, handle syntax errors @@ -93,178 +94,7 @@ def execfile_(filepath, _globals): exec code in _globals -try: - from html import escape as htmlescape -except ImportError: +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 - -# ------------------------------------------------------------------------------ -# Missing builtins and itertools in Python < 2.6 - -if sys.version_info >= (2, 6): - # Python >= 2.6 - next = next - - from itertools import product - try: - from itertools import zip_longest # Python 3 name - except ImportError: - from itertools import izip_longest as zip_longest - - import os - relpath = os.path.relpath - del os - - import io - open = io.open - -else: - # Python < 2.6 - from itertools import izip, repeat, chain - - # this is on Python 2, where the method is called "next" (it is refactored - # to __next__ by 2to3, but in that case never executed) - def next(iterator): - return iterator.next() - - # These replacement functions have been taken from the Python 2.6 - # itertools documentation. - def product(*args, **kwargs): - pools = map(tuple, args) * kwargs.get('repeat', 1) - result = [[]] - for pool in pools: - result = [x + [y] for x in result for y in pool] - for prod in result: - yield tuple(prod) - - def zip_longest(*args, **kwds): - # zip_longest('ABCD', 'xy', fillvalue='-') --> Ax By C- D- - fillvalue = kwds.get('fillvalue') - def sentinel(counter = ([fillvalue]*(len(args)-1)).pop): - yield counter() # yields the fillvalue, or raises IndexError - fillers = repeat(fillvalue) - iters = [chain(it, sentinel(), fillers) for it in args] - try: - for tup in izip(*iters): - yield tup - except IndexError: - pass - - from os.path import curdir - def relpath(path, start=curdir): - """Return a relative version of a path""" - from os.path import sep, abspath, commonprefix, join, pardir - - if not path: - raise ValueError("no path specified") - - start_list = abspath(start).split(sep) - path_list = abspath(path).split(sep) - - # Work out how much of the filepath is shared by start and path. - i = len(commonprefix([start_list, path_list])) - - rel_list = [pardir] * (len(start_list)-i) + path_list[i:] - if not rel_list: - return start - return join(*rel_list) - del curdir - - from types import MethodType - def open(filename, mode='r', *args, **kw): - newline = kw.pop('newline', None) - mode = mode.replace('t', '') - f = codecs.open(filename, mode, *args, **kw) - if newline is not None: - f._write = f.write - def write(self, text): - text = text.replace(u'\r\n', u'\n').replace(u'\n', newline) - self._write(text) - f.write = MethodType(write, f) - return f - - -# ------------------------------------------------------------------------------ -# Missing builtins and codecs in Python < 2.5 - -if sys.version_info >= (2, 5): - # Python >= 2.5 - base_exception = BaseException - any = any - all = all - -else: - # Python 2.4 - base_exception = Exception - - def all(gen): - for i in gen: - if not i: - return False - return True - - def any(gen): - for i in gen: - if i: - return True - return False - - # Python 2.4 doesn't know the utf-8-sig encoding, so deliver it here - - def my_search_function(encoding): - norm_encoding = encodings.normalize_encoding(encoding) - if norm_encoding != 'utf_8_sig': - return None - return (encode, decode, StreamReader, StreamWriter) - - codecs.register(my_search_function) - - # begin code copied from utf_8_sig.py in Python 2.6 - - def encode(input, errors='strict'): - return (codecs.BOM_UTF8 + - codecs.utf_8_encode(input, errors)[0], len(input)) - - def decode(input, errors='strict'): - prefix = 0 - if input[:3] == codecs.BOM_UTF8: - input = input[3:] - prefix = 3 - (output, consumed) = codecs.utf_8_decode(input, errors, True) - return (output, consumed+prefix) - - class StreamWriter(codecs.StreamWriter): - def reset(self): - codecs.StreamWriter.reset(self) - try: - del self.encode - except AttributeError: - pass - - def encode(self, input, errors='strict'): - self.encode = codecs.utf_8_encode - return encode(input, errors) - - class StreamReader(codecs.StreamReader): - def reset(self): - codecs.StreamReader.reset(self) - try: - del self.decode - except AttributeError: - pass - - def decode(self, input, errors='strict'): - if len(input) < 3: - if codecs.BOM_UTF8.startswith(input): - # not enough data to decide if this is a BOM - # => try again on the next call - return (u"", 0) - elif input[:3] == codecs.BOM_UTF8: - self.decode = codecs.utf_8_decode - (output, consumed) = codecs.utf_8_decode(input[3:],errors) - return (output, consumed+3) - # (else) no BOM present - self.decode = codecs.utf_8_decode - return codecs.utf_8_decode(input, errors) - - # end code copied from utf_8_sig.py diff --git a/sphinx/versioning.py b/sphinx/versioning.py index a16751bb5..ccab41d4b 100644 --- a/sphinx/versioning.py +++ b/sphinx/versioning.py @@ -11,8 +11,9 @@ """ from uuid import uuid4 from operator import itemgetter +from itertools import product -from sphinx.util.pycompat import product, zip_longest, all +from sphinx.util.pycompat import zip_longest # anything below that ratio is considered equal/changed diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py index 80080752e..5e2bf93fc 100644 --- a/sphinx/writers/latex.py +++ b/sphinx/writers/latex.py @@ -25,7 +25,6 @@ from sphinx.errors import SphinxError from sphinx.locale import admonitionlabels, _ from sphinx.util import split_into from sphinx.util.osutil import ustrftime -from sphinx.util.pycompat import any from sphinx.util.texescape import tex_escape_map, tex_replace_map from sphinx.util.smartypants import educate_quotes_latex diff --git a/tests/test_autodoc.py b/tests/test_autodoc.py index 63c341f1b..7e60c5fb3 100644 --- a/tests/test_autodoc.py +++ b/tests/test_autodoc.py @@ -737,12 +737,8 @@ def _funky_classmethod(name, b, c, d, docstring=None): some arguments.""" def template(cls, a, b, c, d=4, e=5, f=6): return a, b, c, d, e, f - if sys.version_info >= (2, 5): - from functools import partial - function = partial(template, b=b, c=c, d=d) - else: - def function(cls, a, e=5, f=6): - return template(a, b, c, d, e, f) + from functools import partial + function = partial(template, b=b, c=c, d=d) function.__name__ = name function.__doc__ = docstring return classmethod(function) @@ -774,10 +770,9 @@ class Class(Base): #: should be documented -- süß attr = 'bar' + @property def prop(self): """Property.""" - # stay 2.4 compatible (docstring!) - prop = property(prop, doc="Property.") docattr = 'baz' """should likewise be documented -- süß""" diff --git a/tests/test_intl.py b/tests/test_intl.py index c98220890..c241c0aed 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -16,8 +16,6 @@ from StringIO import StringIO from subprocess import Popen, PIPE from xml.etree import ElementTree -from sphinx.util.pycompat import relpath - from util import test_roots, path, with_app, SkipTest @@ -49,7 +47,7 @@ def setup_module(): for f in [f for f in files if f.endswith('.po')]: po = dirpath / f mo = root / 'xx' / 'LC_MESSAGES' / ( - relpath(po[:-3], root) + '.mo') + os.path.relpath(po[:-3], root) + '.mo') if not mo.parent.exists(): mo.parent.makedirs() try: @@ -75,7 +73,7 @@ def teardown_module(): def elem_gettexts(elem): def itertext(self): # this function copied from Python-2.7 'ElementTree.itertext'. - # for compatibility to Python-2.5, 2.6, 3.1 + # for compatibility to Python-2.6, 3.1 tag = self.tag if not isinstance(tag, basestring) and tag is not None: return diff --git a/tests/test_versioning.py b/tests/test_versioning.py index 6469a33cc..5cff92ffd 100644 --- a/tests/test_versioning.py +++ b/tests/test_versioning.py @@ -15,7 +15,6 @@ from docutils.parsers.rst.directives.html import MetaBody from sphinx import addnodes from sphinx.versioning import add_uids, merge_doctrees, get_ratio -from sphinx.util.pycompat import all from util import test_root, TestApp diff --git a/tests/test_websupport.py b/tests/test_websupport.py index 611a131ac..d950a36c3 100644 --- a/tests/test_websupport.py +++ b/tests/test_websupport.py @@ -11,12 +11,7 @@ import os from StringIO import StringIO - -try: - from functools import wraps -except ImportError: - # functools is new in 2.5 - wraps = lambda f: (lambda w: w) +from functools import wraps from sphinx.websupport import WebSupport from sphinx.websupport.errors import DocumentNotFoundError, \ diff --git a/tests/util.py b/tests/util.py index 4ba89030a..a2f345bf8 100644 --- a/tests/util.py +++ b/tests/util.py @@ -13,12 +13,7 @@ import tempfile import shutil import re from codecs import open - -try: - from functools import wraps -except ImportError: - # functools is new in 2.4 - wraps = lambda f: (lambda w: w) +from functools import wraps from sphinx import application from sphinx.theming import Theme diff --git a/tox.ini b/tox.ini index f1675e901..b03cc9e0a 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist=py25,py26,py27,py31,py32,py33,pypy,du11,du10,du09,du08,du07 +envlist=py26,py27,py31,py32,py33,pypy,du11,du10,du09,du08,du07 [testenv] deps= @@ -12,14 +12,6 @@ commands= {envpython} tests/run.py {posargs} sphinx-build -W -b html -d {envtmpdir}/doctrees doc {envtmpdir}/html -[testenv:py25] -deps= - simplejson==2.5.0 - {[testenv]deps} -setenv= - PIP_INSECURE = 1 - {[testenv]setenv} - [testenv:py33] deps= docutils>=0.10.0 From f7cb510ebd558f16cc3ac6102c0c4a6280ee06ed Mon Sep 17 00:00:00 2001 From: Takayuki Shimizukawa Date: Sun, 15 Dec 2013 16:04:23 +0900 Subject: [PATCH 2/2] Drop python-3.1 and remove support codes --- CHANGES | 2 +- doc/install.rst | 2 +- doc/intro.rst | 2 +- setup.py | 4 ++-- sphinx/highlighting.py | 6 ------ sphinx/util/osutil.py | 2 +- sphinx/util/pycompat.py | 4 ++-- tests/test_intl.py | 2 +- tox.ini | 2 +- 9 files changed, 10 insertions(+), 16 deletions(-) diff --git a/CHANGES b/CHANGES index 3b6c88881..df139ef00 100644 --- a/CHANGES +++ b/CHANGES @@ -4,7 +4,7 @@ Release 1.3 (in development) Change support versions ----------------------- -* Drop Python-2.5. (support code was completely removed) +* Drop Python-2.5, 3.1 (support code was completely removed) diff --git a/doc/install.rst b/doc/install.rst index 828dc3b43..bc969b0be 100644 --- a/doc/install.rst +++ b/doc/install.rst @@ -80,7 +80,7 @@ sidebar and under "Quick Links", click "Windows Installer" to download. .. note:: Currently, Python offers two major versions, 2.x and 3.x. Sphinx 1.3 can run - under Python 2.6, 2.7 and 3.1 to 3.3, with the recommended version being + under Python 2.6, 2.7, 3.2, 3.3, with the recommended version being 2.7. This chapter assumes you have installed Python 2.7. Follow the Windows installer for Python. diff --git a/doc/intro.rst b/doc/intro.rst index f0593cee2..b2c25023e 100644 --- a/doc/intro.rst +++ b/doc/intro.rst @@ -50,7 +50,7 @@ See the :ref:`pertinent section in the FAQ list `. Prerequisites ------------- -Sphinx needs at least **Python 2.6** or **Python 3.1** to run, as well as the +Sphinx needs at least **Python 2.6** or **Python 3.2** to run, as well as the docutils_ and Jinja2_ libraries. Sphinx should work with docutils version 0.7 or some (not broken) SVN trunk snapshot. If you like to have source code highlighting support, you must also install the Pygments_ library. diff --git a/setup.py b/setup.py index 543a319d2..53a4c04b2 100644 --- a/setup.py +++ b/setup.py @@ -44,8 +44,8 @@ A development egg can be found `here `_. ''' -if sys.version_info < (2, 6): - print('ERROR: Sphinx requires at least Python 2.6 to run.') +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.7'] diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py index 7a3927d31..807a18261 100644 --- a/sphinx/highlighting.py +++ b/sphinx/highlighting.py @@ -133,12 +133,6 @@ class PygmentsBridge(object): # just replace all non-ASCII characters. src = src.encode('ascii', 'replace') - if (3, 0) <= sys.version_info < (3, 2): - # Python 3.1 can't process '\r' as linesep. - # `parser.suite("print('hello')\r\n")` cause error. - if '\r\n' in src: - src = src.replace('\r\n', '\n') - if parser is None: return True diff --git a/sphinx/util/osutil.py b/sphinx/util/osutil.py index e8655fe1f..d2f8679ed 100644 --- a/sphinx/util/osutil.py +++ b/sphinx/util/osutil.py @@ -70,7 +70,7 @@ def ensuredir(path): # TODO: This function can be removed because this function is same as os.walk -# of Python2.6, 2.7, 3.1, 3.2, 3.3. +# of Python2.6, 2.7, 3.2, 3.3. # HOWEVER, this function is customized to check UnicodeError that obstacle to # replace the function with the os.walk. def walk(top, topdown=True, followlinks=False): diff --git a/sphinx/util/pycompat.py b/sphinx/util/pycompat.py index 68e6d8fbc..a0e099659 100644 --- a/sphinx/util/pycompat.py +++ b/sphinx/util/pycompat.py @@ -75,8 +75,8 @@ def execfile_(filepath, _globals): finally: f.close() - # py26,py31 accept only LF eol instead of CRLF - if sys.version_info[:2] in ((2, 6), (3, 1)): + # py26 accept only LF eol instead of CRLF + if sys.version_info[:2] == (2, 6): source = source.replace(b('\r\n'), b('\n')) # compile to a code object, handle syntax errors diff --git a/tests/test_intl.py b/tests/test_intl.py index c241c0aed..0119d677f 100644 --- a/tests/test_intl.py +++ b/tests/test_intl.py @@ -73,7 +73,7 @@ def teardown_module(): def elem_gettexts(elem): def itertext(self): # this function copied from Python-2.7 'ElementTree.itertext'. - # for compatibility to Python-2.6, 3.1 + # for compatibility to Python-2.6 tag = self.tag if not isinstance(tag, basestring) and tag is not None: return diff --git a/tox.ini b/tox.ini index b03cc9e0a..006819ef5 100644 --- a/tox.ini +++ b/tox.ini @@ -1,5 +1,5 @@ [tox] -envlist=py26,py27,py31,py32,py33,pypy,du11,du10,du09,du08,du07 +envlist=py26,py27,py32,py33,pypy,du11,du10,du09,du08,du07 [testenv] deps=