From da657c8e326a419cde8ae6ea91be9661b9622504 Mon Sep 17 00:00:00 2001 From: Stefan Behnel Date: Tue, 30 Oct 2018 20:17:36 +0100 Subject: Remove support for Py2.6 and various quirks that special-cased it. Closes #2692. --- .travis.yml | 8 ++---- Cython/Build/Dependencies.py | 42 +++++++++++++---------------- Cython/Compiler/Code.py | 6 ----- Cython/Compiler/Errors.py | 4 --- Cython/Compiler/Main.py | 4 +-- Cython/Compiler/ModuleNode.py | 4 +-- Cython/Debugger/Tests/TestLibCython.py | 4 +-- Cython/Debugger/libpython.py | 6 ++--- Cython/Utility/Builtins.c | 9 ------- Cython/Utility/Capsule.c | 12 ++------- Cython/Utility/CommonStructures.c | 4 --- Cython/Utility/CpdefEnums.pyx | 5 +--- Cython/Utility/ImportExport.c | 48 ---------------------------------- Cython/Utility/ModuleSetupCode.c | 25 +++--------------- Cython/Utility/ObjectHandling.c | 4 +-- runtests.py | 21 +++------------ tests/buffers/userbuffer.pyx | 12 +-------- tests/errors/cdefkwargs.pyx | 4 --- tests/memoryview/memslice.pyx | 6 +---- tests/run/builtin_float.py | 14 +++------- tests/run/c_type_methods_T236.pyx | 7 ++--- tests/run/cpdef_enums.pyx | 10 ++----- tests/run/extstarargs.pyx | 4 +-- tests/run/numpy_test.pyx | 3 +-- tests/run/test_asyncgen.py | 10 ------- tests/run/test_coroutines_pep492.pyx | 19 +++----------- tests/run/test_fstring.pyx | 39 +++++++-------------------- tests/run/test_grammar.py | 28 -------------------- tests/run/unicodeliterals.pyx | 4 --- 29 files changed, 66 insertions(+), 300 deletions(-) diff --git a/.travis.yml b/.travis.yml index da8fad9e1..77e8a2211 100644 --- a/.travis.yml +++ b/.travis.yml @@ -42,10 +42,6 @@ matrix: dist: xenial # Required for Python 3.7 sudo: required # travis-ci/travis-ci#9069 env: BACKEND=cpp - - python: 2.6 - env: BACKEND=c - - python: 2.6 - env: BACKEND=cpp # Disabled: coverage analysis takes excessively long, several times longer than without. # - python: 3.7 # dist: xenial # Required for Python 3.7 @@ -138,7 +134,7 @@ before_install: install: - python -c 'import sys; print("Python %s" % (sys.version,))' - - if [ -n "${TRAVIS_PYTHON_VERSION##*-dev}" -a -n "${TRAVIS_PYTHON_VERSION##2.6*}" ]; then pip install -r test-requirements.txt $( [ -z "${TRAVIS_PYTHON_VERSION##pypy*}" -o -z "${TRAVIS_PYTHON_VERSION##3.7*}" ] || echo " -r test-requirements-cpython.txt" ) ; fi + - if [ -n "${TRAVIS_PYTHON_VERSION##*-dev}" ]; then pip install -r test-requirements.txt $( [ -z "${TRAVIS_PYTHON_VERSION##pypy*}" -o -z "${TRAVIS_PYTHON_VERSION##3.7*}" ] || echo " -r test-requirements-cpython.txt" ) ; fi # - CFLAGS="-O2 -ggdb -Wall -Wextra $(python -c 'import sys; print("-fno-strict-aliasing" if sys.version_info[0] == 2 else "")')" python setup.py build before_script: ccache -s || true @@ -150,7 +146,7 @@ script: else STYLE_ARGS=--no-code-style; if $PYTHON_DBG -V >&2; then CFLAGS="-O0 -ggdb" $PYTHON_DBG runtests.py -vv --no-code-style Debugger --backends=$BACKEND; fi; - if [ -z "${BACKEND##*cpp*}" -a -n "${TRAVIS_PYTHON_VERSION##2.6*}" ]; then pip install pythran; fi; + if [ -z "${BACKEND##*cpp*}" ]; then pip install pythran; fi; if [ "$BACKEND" != "cpp" -a -n "${TRAVIS_PYTHON_VERSION##2*}" ]; then pip install mypy; fi; fi - if [ "$COVERAGE" != "1" ]; then CFLAGS="-O2 -ggdb -Wall -Wextra $(python -c 'import sys; print("-fno-strict-aliasing" if sys.version_info[0] == 2 else "")')" python setup.py build_ext -i; fi diff --git a/Cython/Build/Dependencies.py b/Cython/Build/Dependencies.py index ae98fd74b..d0d83c41a 100644 --- a/Cython/Build/Dependencies.py +++ b/Cython/Build/Dependencies.py @@ -1056,31 +1056,25 @@ def cythonize(module_list, exclude=None, nthreads=0, aliases=None, quiet=False, if N <= 1: nthreads = 0 if nthreads: - # Requires multiprocessing (or Python >= 2.6) + import multiprocessing + pool = multiprocessing.Pool( + nthreads, initializer=_init_multiprocessing_helper) + # This is a bit more involved than it should be, because KeyboardInterrupts + # break the multiprocessing workers when using a normal pool.map(). + # See, for example: + # http://noswap.com/blog/python-multiprocessing-keyboardinterrupt try: - import multiprocessing - pool = multiprocessing.Pool( - nthreads, initializer=_init_multiprocessing_helper) - except (ImportError, OSError): - print("multiprocessing required for parallel cythonization") - nthreads = 0 - else: - # This is a bit more involved than it should be, because KeyboardInterrupts - # break the multiprocessing workers when using a normal pool.map(). - # See, for example: - # http://noswap.com/blog/python-multiprocessing-keyboardinterrupt - try: - result = pool.map_async(cythonize_one_helper, to_compile, chunksize=1) - pool.close() - while not result.ready(): - try: - result.get(99999) # seconds - except multiprocessing.TimeoutError: - pass - except KeyboardInterrupt: - pool.terminate() - raise - pool.join() + result = pool.map_async(cythonize_one_helper, to_compile, chunksize=1) + pool.close() + while not result.ready(): + try: + result.get(99999) # seconds + except multiprocessing.TimeoutError: + pass + except KeyboardInterrupt: + pool.terminate() + raise + pool.join() if not nthreads: for args in to_compile: cythonize_one(*args) diff --git a/Cython/Compiler/Code.py b/Cython/Compiler/Code.py index 232b0406e..e7ccdc5ae 100644 --- a/Cython/Compiler/Code.py +++ b/Cython/Compiler/Code.py @@ -43,8 +43,6 @@ try: except ImportError: from builtins import str as basestring -KEYWORDS_MUST_BE_BYTES = sys.version_info < (2, 7) - non_portable_builtins_map = { # builtins that have different names in different Python versions @@ -259,15 +257,11 @@ class UtilityCodeBase(object): utility[1] = code else: all_tags = utility[2] - if KEYWORDS_MUST_BE_BYTES: - type = type.encode('ASCII') all_tags[type] = code if tags: all_tags = utility[2] for name, values in tags.items(): - if KEYWORDS_MUST_BE_BYTES: - name = name.encode('ASCII') all_tags.setdefault(name, set()).update(values) @classmethod diff --git a/Cython/Compiler/Errors.py b/Cython/Compiler/Errors.py index 9761b52c3..4aa0e903c 100644 --- a/Cython/Compiler/Errors.py +++ b/Cython/Compiler/Errors.py @@ -60,8 +60,6 @@ class CompileError(PyrexError): self.message_only = message self.formatted_message = format_error(message, position) self.reported = False - # Deprecated and withdrawn in 2.6: - # self.message = message Exception.__init__(self, self.formatted_message) # Python Exception subclass pickling is broken, # see http://bugs.python.org/issue1692335 @@ -74,8 +72,6 @@ class CompileWarning(PyrexWarning): def __init__(self, position = None, message = ""): self.position = position - # Deprecated and withdrawn in 2.6: - # self.message = message Exception.__init__(self, format_position(position) + message) class InternalError(Exception): diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py index 0f1ff4d33..9465edab3 100644 --- a/Cython/Compiler/Main.py +++ b/Cython/Compiler/Main.py @@ -9,8 +9,8 @@ import re import sys import io -if sys.version_info[:2] < (2, 6) or (3, 0) <= sys.version_info[:2] < (3, 3): - sys.stderr.write("Sorry, Cython requires Python 2.6+ or 3.3+, found %d.%d\n" % tuple(sys.version_info[:2])) +if sys.version_info[:2] < (2, 7) or (3, 0) <= sys.version_info[:2] < (3, 3): + sys.stderr.write("Sorry, Cython requires Python 2.7 or 3.3+, found %d.%d\n" % tuple(sys.version_info[:2])) sys.exit(1) try: diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index ce1a94289..c256ef883 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -635,9 +635,9 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln("#ifndef Py_PYTHON_H") code.putln(" #error Python headers needed to compile C extensions, " "please install development version of Python.") - code.putln("#elif PY_VERSION_HEX < 0x02060000 || " + code.putln("#elif PY_VERSION_HEX < 0x02070000 || " "(0x03000000 <= PY_VERSION_HEX && PY_VERSION_HEX < 0x03030000)") - code.putln(" #error Cython requires Python 2.6+ or Python 3.3+.") + code.putln(" #error Cython requires Python 2.7+ or Python 3.3+.") code.putln("#else") code.globalstate["end"].putln("#endif /* Py_PYTHON_H */") diff --git a/Cython/Debugger/Tests/TestLibCython.py b/Cython/Debugger/Tests/TestLibCython.py index b789b1062..2e2891039 100644 --- a/Cython/Debugger/Tests/TestLibCython.py +++ b/Cython/Debugger/Tests/TestLibCython.py @@ -56,13 +56,13 @@ def test_gdb(): stdout, _ = p.communicate() try: internal_python_version = list(map(int, stdout.decode('ascii', 'ignore').split())) - if internal_python_version < [2, 6]: + if internal_python_version < [2, 7]: have_gdb = False except ValueError: have_gdb = False if not have_gdb: - warnings.warn('Skipping gdb tests, need gdb >= 7.2 with Python >= 2.6') + warnings.warn('Skipping gdb tests, need gdb >= 7.2 with Python >= 2.7') return have_gdb diff --git a/Cython/Debugger/libpython.py b/Cython/Debugger/libpython.py index fea626dd7..66d121040 100644 --- a/Cython/Debugger/libpython.py +++ b/Cython/Debugger/libpython.py @@ -48,7 +48,7 @@ The module also extends gdb with some python-specific commands. ''' # NOTE: some gdbs are linked with Python 3, so this file should be dual-syntax -# compatible (2.6+ and 3.0+). See #19308. +# compatible (2.7+ and 3.3+). See #19308. from __future__ import print_function import gdb @@ -1435,8 +1435,8 @@ The following code should ensure that the prettyprinter is registered if the code is autoloaded by gdb when visiting libpython.so, provided that this python file is installed to the same path as the library (or its .debug file) plus a "-gdb.py" suffix, e.g: - /usr/lib/libpython2.6.so.1.0-gdb.py - /usr/lib/debug/usr/lib/libpython2.6.so.1.0.debug-gdb.py + /usr/lib/libpython3.7.so.1.0-gdb.py + /usr/lib/debug/usr/lib/libpython3.7.so.1.0.debug-gdb.py """ def register (obj): if obj is None: diff --git a/Cython/Utility/Builtins.c b/Cython/Utility/Builtins.c index 27a551213..df5c41fbc 100644 --- a/Cython/Utility/Builtins.c +++ b/Cython/Utility/Builtins.c @@ -418,9 +418,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_IterItems(PyObject* d) { //////////////////// py_dict_viewkeys.proto //////////////////// -#if PY_VERSION_HEX < 0x02070000 -#error This module uses dict views, which require Python 2.7 or later -#endif static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d); /*proto*/ //////////////////// py_dict_viewkeys //////////////////// @@ -434,9 +431,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewKeys(PyObject* d) { //////////////////// py_dict_viewvalues.proto //////////////////// -#if PY_VERSION_HEX < 0x02070000 -#error This module uses dict views, which require Python 2.7 or later -#endif static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d); /*proto*/ //////////////////// py_dict_viewvalues //////////////////// @@ -450,9 +444,6 @@ static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewValues(PyObject* d) { //////////////////// py_dict_viewitems.proto //////////////////// -#if PY_VERSION_HEX < 0x02070000 -#error This module uses dict views, which require Python 2.7 or later -#endif static CYTHON_INLINE PyObject* __Pyx_PyDict_ViewItems(PyObject* d); /*proto*/ //////////////////// py_dict_viewitems //////////////////// diff --git a/Cython/Utility/Capsule.c b/Cython/Utility/Capsule.c index cc4fe0d88..14c744cdf 100644 --- a/Cython/Utility/Capsule.c +++ b/Cython/Utility/Capsule.c @@ -6,15 +6,7 @@ static CYTHON_INLINE PyObject *__pyx_capsule_create(void *p, const char *sig); //////////////// Capsule //////////////// static CYTHON_INLINE PyObject * -__pyx_capsule_create(void *p, CYTHON_UNUSED const char *sig) +__pyx_capsule_create(void *p, const char *sig) { - PyObject *cobj; - -#if PY_VERSION_HEX >= 0x02070000 - cobj = PyCapsule_New(p, sig, NULL); -#else - cobj = PyCObject_FromVoidPtr(p, NULL); -#endif - - return cobj; + return PyCapsule_New(p, sig, NULL); } diff --git a/Cython/Utility/CommonStructures.c b/Cython/Utility/CommonStructures.c index c7945feb4..dfbacb2ab 100644 --- a/Cython/Utility/CommonStructures.c +++ b/Cython/Utility/CommonStructures.c @@ -56,7 +56,6 @@ static void* __Pyx_FetchCommonPointer(void* pointer, const char* name); static void* __Pyx_FetchCommonPointer(void* pointer, const char* name) { -#if PY_VERSION_HEX >= 0x02070000 PyObject* fake_module = NULL; PyObject* capsule = NULL; void* value = NULL; @@ -80,7 +79,4 @@ bad: Py_XDECREF(capsule); Py_DECREF(fake_module); return value; -#else - return pointer; -#endif } diff --git a/Cython/Utility/CpdefEnums.pyx b/Cython/Utility/CpdefEnums.pyx index 148d776c2..546551f14 100644 --- a/Cython/Utility/CpdefEnums.pyx +++ b/Cython/Utility/CpdefEnums.pyx @@ -6,10 +6,7 @@ cdef extern from *: int PY_VERSION_HEX cdef object __Pyx_OrderedDict -if PY_VERSION_HEX >= 0x02070000: - from collections import OrderedDict as __Pyx_OrderedDict -else: - __Pyx_OrderedDict = dict +from collections import OrderedDict as __Pyx_OrderedDict @cython.internal cdef class __Pyx_EnumMeta(type): diff --git a/Cython/Utility/ImportExport.c b/Cython/Utility/ImportExport.c index 670346723..bd18c7640 100644 --- a/Cython/Utility/ImportExport.c +++ b/Cython/Utility/ImportExport.c @@ -412,7 +412,6 @@ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (** PyModule_GetName(module), funcname); goto bad; } -#if PY_VERSION_HEX >= 0x02070000 if (!PyCapsule_IsValid(cobj, sig)) { PyErr_Format(PyExc_TypeError, "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", @@ -420,21 +419,6 @@ static int __Pyx_ImportFunction(PyObject *module, const char *funcname, void (** goto bad; } tmp.p = PyCapsule_GetPointer(cobj, sig); -#else - {const char *desc, *s1, *s2; - desc = (const char *)PyCObject_GetDesc(cobj); - if (!desc) - goto bad; - s1 = desc; s2 = sig; - while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } - if (*s1 != *s2) { - PyErr_Format(PyExc_TypeError, - "C function %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", - PyModule_GetName(module), funcname, sig, desc); - goto bad; - } - tmp.p = PyCObject_AsVoidPtr(cobj);} -#endif *f = tmp.fp; if (!(*f)) goto bad; @@ -472,11 +456,7 @@ static int __Pyx_ExportFunction(const char *name, void (*f)(void), const char *s goto bad; } tmp.fp = f; -#if PY_VERSION_HEX >= 0x02070000 cobj = PyCapsule_New(tmp.p, sig, 0); -#else - cobj = PyCObject_FromVoidPtrAndDesc(tmp.p, (void *)sig, 0); -#endif if (!cobj) goto bad; if (PyDict_SetItemString(d, name, cobj) < 0) @@ -513,7 +493,6 @@ static int __Pyx_ImportVoidPtr(PyObject *module, const char *name, void **p, con PyModule_GetName(module), name); goto bad; } -#if PY_VERSION_HEX >= 0x02070000 if (!PyCapsule_IsValid(cobj, sig)) { PyErr_Format(PyExc_TypeError, "C variable %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", @@ -521,21 +500,6 @@ static int __Pyx_ImportVoidPtr(PyObject *module, const char *name, void **p, con goto bad; } *p = PyCapsule_GetPointer(cobj, sig); -#else - {const char *desc, *s1, *s2; - desc = (const char *)PyCObject_GetDesc(cobj); - if (!desc) - goto bad; - s1 = desc; s2 = sig; - while (*s1 != '\0' && *s1 == *s2) { s1++; s2++; } - if (*s1 != *s2) { - PyErr_Format(PyExc_TypeError, - "C variable %.200s.%.200s has wrong signature (expected %.500s, got %.500s)", - PyModule_GetName(module), name, sig, desc); - goto bad; - } - *p = PyCObject_AsVoidPtr(cobj);} -#endif if (!(*p)) goto bad; Py_DECREF(d); @@ -567,11 +531,7 @@ static int __Pyx_ExportVoidPtr(PyObject *name, void *p, const char *sig) { if (__Pyx_PyObject_SetAttrStr($module_cname, PYIDENT("$api_name"), d) < 0) goto bad; } -#if PY_VERSION_HEX >= 0x02070000 cobj = PyCapsule_New(p, sig, 0); -#else - cobj = PyCObject_FromVoidPtrAndDesc(p, (void *)sig, 0); -#endif if (!cobj) goto bad; if (PyDict_SetItem(d, name, cobj) < 0) @@ -593,11 +553,7 @@ static int __Pyx_SetVtable(PyObject *dict, void *vtable); /*proto*/ /////////////// SetVTable /////////////// static int __Pyx_SetVtable(PyObject *dict, void *vtable) { -#if PY_VERSION_HEX >= 0x02070000 PyObject *ob = PyCapsule_New(vtable, 0, 0); -#else - PyObject *ob = PyCObject_FromVoidPtr(vtable, 0); -#endif if (!ob) goto bad; if (PyDict_SetItem(dict, PYIDENT("__pyx_vtable__"), ob) < 0) @@ -621,11 +577,7 @@ static void* __Pyx_GetVtable(PyObject *dict) { PyObject *ob = PyObject_GetItem(dict, PYIDENT("__pyx_vtable__")); if (!ob) goto bad; -#if PY_VERSION_HEX >= 0x02070000 ptr = PyCapsule_GetPointer(ob, 0); -#else - ptr = PyCObject_AsVoidPtr(ob); -#endif if (!ptr && !PyErr_Occurred()) PyErr_SetString(PyExc_RuntimeError, "invalid vtable found for imported type"); Py_DECREF(ob); diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c index 15422902e..6a9f75b20 100644 --- a/Cython/Utility/ModuleSetupCode.c +++ b/Cython/Utility/ModuleSetupCode.c @@ -29,9 +29,7 @@ #ifndef HAVE_LONG_LONG // CPython has required PY_LONG_LONG support for years, even if HAVE_LONG_LONG is not defined for us - #if PY_VERSION_HEX >= 0x02070000 - #define HAVE_LONG_LONG - #endif + #define HAVE_LONG_LONG #endif #ifndef PY_LONG_LONG @@ -135,11 +133,7 @@ #ifndef CYTHON_USE_TYPE_SLOTS #define CYTHON_USE_TYPE_SLOTS 1 #endif - #if PY_VERSION_HEX < 0x02070000 - // looks like calling _PyType_Lookup() isn't safe in Py<=2.6/3.1 - #undef CYTHON_USE_PYTYPE_LOOKUP - #define CYTHON_USE_PYTYPE_LOOKUP 0 - #elif !defined(CYTHON_USE_PYTYPE_LOOKUP) + #ifndef CYTHON_USE_PYTYPE_LOOKUP #define CYTHON_USE_PYTYPE_LOOKUP 1 #endif #if PY_MAJOR_VERSION < 3 @@ -148,10 +142,7 @@ #elif !defined(CYTHON_USE_ASYNC_SLOTS) #define CYTHON_USE_ASYNC_SLOTS 1 #endif - #if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_USE_PYLONG_INTERNALS - #define CYTHON_USE_PYLONG_INTERNALS 0 - #elif !defined(CYTHON_USE_PYLONG_INTERNALS) + #ifndef CYTHON_USE_PYLONG_INTERNALS #define CYTHON_USE_PYLONG_INTERNALS 1 #endif #ifndef CYTHON_USE_PYLIST_INTERNALS @@ -470,7 +461,7 @@ class __Pyx_FakeReference { #define __Pyx_PyFrame_SetLineNumber(frame, lineno) (frame)->f_lineno = (lineno) #endif -#if !CYTHON_FAST_THREAD_STATE || PY_VERSION_HEX < 0x02070000 +#if !CYTHON_FAST_THREAD_STATE #define __Pyx_PyThreadState_Current PyThreadState_GET() #elif PY_VERSION_HEX >= 0x03060000 //#elif PY_VERSION_HEX >= 0x03050200 @@ -1396,10 +1387,6 @@ static void __Pyx_FastGilFuncInit(void); #define __Pyx_FastGIL_PyCapsule \ __Pyx_FastGIL_ABI_module "." __Pyx_FastGIL_PyCapsuleName -#if PY_VERSION_HEX < 0x02070000 - #undef CYTHON_THREAD_LOCAL -#endif - #ifdef CYTHON_THREAD_LOCAL #include "pythread.h" @@ -1492,11 +1479,7 @@ static void __Pyx_FastGilFuncInit0(void) { #endif static void __Pyx_FastGilFuncInit(void) { -#if PY_VERSION_HEX >= 0x02070000 struct __Pyx_FastGilVtab* shared = (struct __Pyx_FastGilVtab*)PyCapsule_Import(__Pyx_FastGIL_PyCapsule, 1); -#else - struct __Pyx_FastGilVtab* shared = NULL; -#endif if (shared) { __Pyx_FastGilFuncs = *shared; } else { diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c index b147cb33e..75088f431 100644 --- a/Cython/Utility/ObjectHandling.c +++ b/Cython/Utility/ObjectHandling.c @@ -199,10 +199,8 @@ static CYTHON_INLINE PyObject *__Pyx_PyIter_Next2(PyObject* iterator, PyObject* next = iternext(iterator); if (likely(next)) return next; - #if PY_VERSION_HEX >= 0x02070000 if (unlikely(iternext == &_PyObject_NextNotImplemented)) return NULL; - #endif #else // Since the slot was set, assume that PyIter_Next() will likely succeed, and properly fail otherwise. // Note: PyIter_Next() crashes in CPython if "tp_iternext" is NULL. @@ -1303,7 +1301,7 @@ static PyObject *__Pyx_RaiseGenericGetAttributeError(PyTypeObject *tp, PyObject } static CYTHON_INLINE PyObject* __Pyx_PyObject_GenericGetAttrNoDict(PyObject* obj, PyObject* attr_name) { - // Copied and adapted from _PyObject_GenericGetAttrWithDict() in CPython 2.6/3.7. + // Copied and adapted from _PyObject_GenericGetAttrWithDict() in CPython 3.6/3.7. // To be used in the "tp_getattro" slot of extension types that have no instance dict and cannot be subclassed. PyObject *descr; PyTypeObject *tp = Py_TYPE(obj); diff --git a/runtests.py b/runtests.py index 69cc1db7c..d5472e188 100755 --- a/runtests.py +++ b/runtests.py @@ -412,12 +412,7 @@ EXT_EXTRAS = { VER_DEP_MODULES = { # tests are excluded if 'CurrentPythonVersion OP VersionTuple', i.e. # (2,4) : (operator.lt, ...) excludes ... when PyVer < 2.4.x - (2,7) : (operator.lt, lambda x: x in ['run.withstat_py27', # multi context with statement - 'run.yield_inside_lambda', - 'run.test_dictviews', - 'run.pyclass_special_methods', - 'run.set_literals', - ]), + # The next line should start (3,); but this is a dictionary, so # we can only have one (3,) key. Since 2.7 is supposed to be the # last 2.x release, things would have to change drastically for this @@ -1260,8 +1255,7 @@ class CythonRunTestCase(CythonCompileTestCase): try: self.success = False ext_so_path = self.runCompileTest() - # Py2.6 lacks "_TextTestResult.skipped" - failures, errors, skipped = len(result.failures), len(result.errors), len(getattr(result, 'skipped', [])) + failures, errors, skipped = len(result.failures), len(result.errors), len(result.skipped) if not self.cython_only and ext_so_path is not None: self.run_tests(result, ext_so_path) if failures == len(result.failures) and errors == len(result.errors): @@ -1445,10 +1439,6 @@ class PartialTestResult(_TextTestResult): _TextTestResult.__init__( self, self._StringIO(), True, base_result.dots + base_result.showAll*2) - try: - self.skipped - except AttributeError: - self.skipped = [] # Py2.6 def strip_error_results(self, results): for test_case, error in results: @@ -1473,10 +1463,7 @@ class PartialTestResult(_TextTestResult): if output: result.stream.write(output) result.errors.extend(errors) - try: - result.skipped.extend(skipped) - except AttributeError: - pass # Py2.6 + result.skipped.extend(skipped) result.failures.extend(failures) result.testsRun += tests_run @@ -2209,7 +2196,7 @@ def time_stamper_thread(interval=10): write('\n#### %s\n' % now()) thread = threading.Thread(target=time_stamper, name='time_stamper') - thread.setDaemon(True) # Py2.6 ... + thread.setDaemon(True) # Py2 ... thread.start() try: yield diff --git a/tests/buffers/userbuffer.pyx b/tests/buffers/userbuffer.pyx index b9c871970..df774a07b 100644 --- a/tests/buffers/userbuffer.pyx +++ b/tests/buffers/userbuffer.pyx @@ -1,21 +1,11 @@ -import sys -__doc__ = u"" - -if sys.version_info[:2] == (2, 6): - __doc__ += u""" ->>> memoryview = _memoryview -""" - -__doc__ += u""" +__doc__ = u""" >>> b1 = UserBuffer1() >>> m1 = memoryview(b1) >>> m1.tolist() [0, 1, 2, 3, 4] >>> del m1, b1 -""" -__doc__ += u""" >>> b2 = UserBuffer2() >>> m2 = memoryview(b2) UserBuffer2: getbuffer diff --git a/tests/errors/cdefkwargs.pyx b/tests/errors/cdefkwargs.pyx index a4477e2da..2fedeb04a 100644 --- a/tests/errors/cdefkwargs.pyx +++ b/tests/errors/cdefkwargs.pyx @@ -6,10 +6,6 @@ __doc__ = u""" >>> call4() """ -import sys, re -if sys.version_info >= (2,6): - __doc__ = re.sub(u"Error: (.*)exactly(.*)", u"Error: \\1at most\\2", __doc__) - # the calls: def call2(): diff --git a/tests/memoryview/memslice.pyx b/tests/memoryview/memslice.pyx index 4d280b85a..0b448d597 100644 --- a/tests/memoryview/memslice.pyx +++ b/tests/memoryview/memslice.pyx @@ -1853,11 +1853,7 @@ def test_struct_attributes_format(): """ cdef TestAttrs[10] array cdef TestAttrs[:] struct_memview = array - - if sys.version_info[:2] >= (2, 7): - print builtins.memoryview(struct_memview).format - else: - print "T{i:int_attrib:c:char_attrib:}" + print builtins.memoryview(struct_memview).format # Test padding at the end of structs in the buffer support diff --git a/tests/run/builtin_float.py b/tests/run/builtin_float.py index f2eff2be8..a5a7615d9 100644 --- a/tests/run/builtin_float.py +++ b/tests/run/builtin_float.py @@ -1,6 +1,4 @@ -import sys - def empty_float(): """ >>> float() @@ -11,24 +9,20 @@ def empty_float(): x = float() return x + def float_conjugate(): """ >>> float_call_conjugate() 1.5 """ - if sys.version_info >= (2,6): - x = 1.5 .conjugate() - else: - x = 1.5 + x = 1.5 .conjugate() return x + def float_call_conjugate(): """ >>> float_call_conjugate() 1.5 """ - if sys.version_info >= (2,6): - x = float(1.5).conjugate() - else: - x = 1.5 + x = float(1.5).conjugate() return x diff --git a/tests/run/c_type_methods_T236.pyx b/tests/run/c_type_methods_T236.pyx index 5ac22feae..53f20e661 100644 --- a/tests/run/c_type_methods_T236.pyx +++ b/tests/run/c_type_methods_T236.pyx @@ -1,10 +1,8 @@ # ticket: 236 -__doc__ = '' - import sys -if sys.version_info >= (2,6): - __doc__ += ''' + +__doc__ = ''' >>> float_is_integer(1.0) True >>> float_is_integer(1.1) @@ -19,7 +17,6 @@ True ''' def float_is_integer(float f): - # requires Python 2.6+ return f.is_integer() def int_bit_length(int i): diff --git a/tests/run/cpdef_enums.pyx b/tests/run/cpdef_enums.pyx index d2e09454f..5da7bf78c 100644 --- a/tests/run/cpdef_enums.pyx +++ b/tests/run/cpdef_enums.pyx @@ -70,14 +70,8 @@ def test_as_variable_from_cython(): """ >>> test_as_variable_from_cython() """ - import sys - if sys.version_info >= (2, 7): - assert list(PyxEnum) == [TWO, THREE, FIVE], list(PyxEnum) - assert list(PxdEnum) == [RANK_0, RANK_1, RANK_2], list(PxdEnum) - else: - # No OrderedDict. - assert set(PyxEnum) == {TWO, THREE, FIVE}, list(PyxEnum) - assert set(PxdEnum) == {RANK_0, RANK_1, RANK_2}, list(PxdEnum) + assert list(PyxEnum) == [TWO, THREE, FIVE], list(PyxEnum) + assert list(PxdEnum) == [RANK_0, RANK_1, RANK_2], list(PxdEnum) cdef int verify_pure_c() nogil: cdef int x = TWO diff --git a/tests/run/extstarargs.pyx b/tests/run/extstarargs.pyx index 041603865..b657b42fd 100644 --- a/tests/run/extstarargs.pyx +++ b/tests/run/extstarargs.pyx @@ -88,15 +88,13 @@ __doc__ = u""" (1, ('a', 1), ('b', 2)) """ -import sys, re -if sys.version_info >= (2,6): - __doc__ = re.sub(u"(ELLIPSIS[^>]*Error: )[^\n]*\n", u"\\1...\n", __doc__) cdef sorteditems(d): l = list(d.items()) l.sort() return tuple(l) + cdef class Silly: def __init__(self, *a): diff --git a/tests/run/numpy_test.pyx b/tests/run/numpy_test.pyx index c706fec71..619ccc0e1 100644 --- a/tests/run/numpy_test.pyx +++ b/tests/run/numpy_test.pyx @@ -5,7 +5,6 @@ cimport numpy as np cimport cython import re -import sys def little_endian(): @@ -20,7 +19,7 @@ def testcase(f): def testcase_have_buffer_interface(f): major, minor, *rest = np.__version__.split('.') - if (int(major), int(minor)) >= (1, 5) and sys.version_info[:2] >= (2, 6): + if (int(major), int(minor)) >= (1, 5): __test__[f.__name__] = f.__doc__ return f diff --git a/tests/run/test_asyncgen.py b/tests/run/test_asyncgen.py index 558f13574..de4fa4855 100644 --- a/tests/run/test_asyncgen.py +++ b/tests/run/test_asyncgen.py @@ -247,16 +247,6 @@ class AsyncGenTest(unittest.TestCase): else: self.assertTrue(False) - if sys.version_info < (2, 7): - def assertIn(self, x, container): - self.assertTrue(x in container) - - def assertIs(self, x, y): - self.assertTrue(x is y) - - assertRaises = assertRaisesRegex - - def compare_generators(self, sync_gen, async_gen): def sync_iterate(g): res = [] diff --git a/tests/run/test_coroutines_pep492.pyx b/tests/run/test_coroutines_pep492.pyx index 09a3853d5..b7db9f92f 100644 --- a/tests/run/test_coroutines_pep492.pyx +++ b/tests/run/test_coroutines_pep492.pyx @@ -144,17 +144,6 @@ def silence_coro_gc(): gc.collect() -def min_py27(method): - return None if sys.version_info < (2, 7) else method - - -def ignore_py26(manager): - @contextlib.contextmanager - def dummy(): - yield - return dummy() if sys.version_info < (2, 7) else manager - - @contextlib.contextmanager def captured_stderr(): try: @@ -1826,7 +1815,7 @@ class CoroutineTest(unittest.TestCase): buffer = [] async def test1(): - with ignore_py26(self.assertWarnsRegex(DeprecationWarning, "legacy")): + with self.assertWarnsRegex(DeprecationWarning, "legacy"): async for i1, i2 in AsyncIter(): buffer.append(i1 + i2) @@ -1840,7 +1829,7 @@ class CoroutineTest(unittest.TestCase): buffer = [] async def test2(): nonlocal buffer - with ignore_py26(self.assertWarnsRegex(DeprecationWarning, "legacy")): + with self.assertWarnsRegex(DeprecationWarning, "legacy"): async for i in AsyncIter(): buffer.append(i[0]) if i[0] == 20: @@ -1859,7 +1848,7 @@ class CoroutineTest(unittest.TestCase): buffer = [] async def test3(): nonlocal buffer - with ignore_py26(self.assertWarnsRegex(DeprecationWarning, "legacy")): + with self.assertWarnsRegex(DeprecationWarning, "legacy"): async for i in AsyncIter(): if i[0] > 20: continue @@ -2076,7 +2065,6 @@ class CoroutineTest(unittest.TestCase): self.assertEqual(CNT, 0) # old-style pre-Py3.5.2 protocol - no longer supported - @min_py27 def __test_for_9(self): # Test that DeprecationWarning can safely be converted into # an exception (__aiter__ should not have a chance to raise @@ -2094,7 +2082,6 @@ class CoroutineTest(unittest.TestCase): run_async(foo()) # old-style pre-Py3.5.2 protocol - no longer supported - @min_py27 def __test_for_10(self): # Test that DeprecationWarning can safely be converted into # an exception. diff --git a/tests/run/test_fstring.pyx b/tests/run/test_fstring.pyx index 309696c28..450f39f3e 100644 --- a/tests/run/test_fstring.pyx +++ b/tests/run/test_fstring.pyx @@ -10,7 +10,6 @@ import contextlib import sys IS_PY2 = sys.version_info[0] < 3 -IS_PY26 = sys.version_info[:2] < (2, 7) from Cython.Build.Inline import cython_inline from Cython.TestUtils import CythonTest @@ -63,23 +62,8 @@ class TestCase(CythonTest): first = stripped_first.decode('unicode_escape') super(TestCase, self).assertEqual(first, second, msg) - if IS_PY26: - @contextlib.contextmanager - def assertRaises(self, exc): - try: - yield - except exc: - pass - else: - assert False, "exception '%s' not raised" % exc - - def assertIn(self, value, collection): - self.assertTrue(value in collection) - def test__format__lookup(self): - if IS_PY26: - return - elif IS_PY2: + if IS_PY2: raise unittest.SkipTest("Py3-only") # Make sure __format__ is looked up on the type, not the instance. @@ -288,12 +272,11 @@ f'{a * x()}'""" width = 10 precision = 4 value = decimal.Decimal('12.34567') - if not IS_PY26: - self.assertEqual(f'result: {value:{width}.{precision}}', 'result: 12.35') - self.assertEqual(f'result: {value:{width!r}.{precision}}', 'result: 12.35') - self.assertEqual(f'result: {value:{width:0}.{precision:1}}', 'result: 12.35') - self.assertEqual(f'result: {value:{1}{0:0}.{precision:1}}', 'result: 12.35') - self.assertEqual(f'result: {value:{ 1}{ 0:0}.{ precision:1}}', 'result: 12.35') + self.assertEqual(f'result: {value:{width}.{precision}}', 'result: 12.35') + self.assertEqual(f'result: {value:{width!r}.{precision}}', 'result: 12.35') + self.assertEqual(f'result: {value:{width:0}.{precision:1}}', 'result: 12.35') + self.assertEqual(f'result: {value:{1}{0:0}.{precision:1}}', 'result: 12.35') + self.assertEqual(f'result: {value:{ 1}{ 0:0}.{ precision:1}}', 'result: 12.35') self.assertEqual(f'{10:#{1}0x}', ' 0xa') self.assertEqual(f'{10:{"#"}1{0}{"x"}}', ' 0xa') self.assertEqual(f'{-10:-{"#"}1{0}x}', ' -0xa') @@ -312,8 +295,7 @@ f'{a * x()}'""" ]) # CYTHON: The nesting restriction seems rather arbitrary. Ignoring it for now and instead test that it works. - if not IS_PY26: - self.assertEqual(f'result: {value:{width:{0}}.{precision:1}}', 'result: 12.35') + self.assertEqual(f'result: {value:{width:{0}}.{precision:1}}', 'result: 12.35') #self.assertAllRaise(SyntaxError, "f-string: expressions nested too deeply", # [# Can't nest format specifiers. # "f'result: {value:{width:{0}}.{precision:1}}'", @@ -678,10 +660,9 @@ f'{a * x()}'""" def test_conversions(self): self.assertEqual(f'{3.14:10.10}', ' 3.14') - if not IS_PY26: - self.assertEqual(f'{3.14!s:10.10}', '3.14 ') - self.assertEqual(f'{3.14!r:10.10}', '3.14 ') - self.assertEqual(f'{3.14!a:10.10}', '3.14 ') + self.assertEqual(f'{3.14!s:10.10}', '3.14 ') + self.assertEqual(f'{3.14!r:10.10}', '3.14 ') + self.assertEqual(f'{3.14!a:10.10}', '3.14 ') self.assertEqual(f'{"a"}', 'a') self.assertEqual(f'{"a"!r}', "'a'") diff --git a/tests/run/test_grammar.py b/tests/run/test_grammar.py index 3bdadbefa..37a243575 100644 --- a/tests/run/test_grammar.py +++ b/tests/run/test_grammar.py @@ -1520,24 +1520,6 @@ class GrammarTests(unittest.TestCase): GrammarTests.assertRaisesRegex = lambda self, exc, msg: self.assertRaises(exc) -if sys.version_info < (2, 7): - def assertRaises(self, exc_type, func=None, *args, **kwargs): - if func is not None: - return unittest.TestCase.assertRaises(self, exc_type, func, *args, **kwargs) - @contextlib.contextmanager - def assertRaisesCM(): - class Result(object): - exception = exc_type("unexpected EOF") # see usage above - try: - yield Result() - except exc_type: - self.assertTrue(True) - else: - self.assertTrue(False) - return assertRaisesCM() - GrammarTests.assertRaises = assertRaises - TokenTests.assertRaises = assertRaises - if not hasattr(unittest.TestCase, 'subTest'): @contextlib.contextmanager @@ -1550,20 +1532,10 @@ if not hasattr(unittest.TestCase, 'subTest'): GrammarTests.subTest = subTest -if not hasattr(unittest.TestCase, 'assertIn'): - def assertIn(self, member, container, msg=None): - self.assertTrue(member in container, msg) - TokenTests.assertIn = assertIn - - # FIXME: disabling some tests for real Cython bugs here del GrammarTests.test_comprehension_specials # iterable pre-calculation in generator expression del GrammarTests.test_funcdef # annotation mangling -# this test is difficult to enable in Py2.6 -if sys.version_info < (2,7): - del GrammarTests.test_former_statements_refer_to_builtins - if __name__ == '__main__': unittest.main() diff --git a/tests/run/unicodeliterals.pyx b/tests/run/unicodeliterals.pyx index 7d4806ef1..9a9b20142 100644 --- a/tests/run/unicodeliterals.pyx +++ b/tests/run/unicodeliterals.pyx @@ -87,11 +87,7 @@ __doc__ = br""" True >>> ustring_in_constant_tuple == ('a', u'abc', u'\\N{SNOWMAN}', u'x' * 3, u'\\N{SNOWMAN}' * 4 + u'O') or ustring_in_constant_tuple # unescaped by Python True -""" -if sys.version_info >= (2,6,5): - # this doesn't work well in older Python versions - __doc__ += u"""\ >>> expected = u'\U00101234' # unescaped by Cython >>> if wide_literal == expected: print(True) ... else: print(repr(wide_literal), repr(expected), sys.maxunicode) -- cgit v1.2.1