From: DongHun Kwak Date: Thu, 31 Dec 2020 03:10:24 +0000 (+0900) Subject: Imported Upstream version 0.29.11 X-Git-Tag: upstream/0.29.11^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=b416d6a030bccb33c5edc8874126aa92047838e5;p=platform%2Fupstream%2Fpython3-cython.git Imported Upstream version 0.29.11 --- diff --git a/CHANGES.rst b/CHANGES.rst index 1595106..7f37af2 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,6 +2,35 @@ Cython Changelog ================ +0.29.11 (2019-06-30) +==================== + +Bugs fixed +---------- + +* Fix compile error in CPython 3.8b2. + Patch by Nick Coghlan. (Github issue #3009) + +* Invalid C code generated for lambda functions in cdef methods. + Patch by Josh Tobin. (Github issue #2967) + +* Support slice handling in newer Pythran versions. + Patch by Serge Guelton. (Github issue #2989) + +* A reference leak in power-of-2 calculation was fixed. + Patch by Sebastian Berg. (Github issue #3022) + +* The search order for include files was changed. Previously it was + ``include_directories``, ``Cython/Includes``, ``sys.path``. Now it is + ``include_directories``, ``sys.path``, ``Cython/Includes``. This was done to + allow third-party ``*.pxd`` files to override the ones in Cython. + Original patch by Matti Picus. (Github issue #2905) + +* Setting ``language_level=2`` in a file did not work if ``language_level=3`` + was enabled globally before. + Patch by Jeroen Demeyer. (Github issue #2791) + + 0.29.10 (2019-06-02) ==================== diff --git a/Cython/Build/Dependencies.py b/Cython/Build/Dependencies.py index fbd44e7..a4e5c60 100644 --- a/Cython/Build/Dependencies.py +++ b/Cython/Build/Dependencies.py @@ -34,10 +34,8 @@ except ImportError: try: import pythran - import pythran.config - pythran_version = pythran.__version__ except: - pythran_version = None + pythran = None from .. import Utils from ..Utils import (cached_function, cached_method, path_exists, @@ -125,13 +123,13 @@ def file_hash(filename): def update_pythran_extension(ext): - if not pythran_version: + if pythran is None: raise RuntimeError("You first need to install Pythran to use the np_pythran directive.") - pythran_ext = ( - pythran.config.make_extension(python=True) - if pythran_version >= '0.9' or pythran_version >= '0.8.7' - else pythran.config.make_extension() - ) + try: + pythran_ext = pythran.config.make_extension(python=True) + except TypeError: # older pythran version only + pythran_ext = pythran.config.make_extension() + ext.include_dirs.extend(pythran_ext['include_dirs']) ext.extra_compile_args.extend(pythran_ext['extra_compile_args']) ext.extra_link_args.extend(pythran_ext['extra_link_args']) @@ -947,8 +945,9 @@ def cythonize(module_list, exclude=None, nthreads=0, aliases=None, quiet=False, if 'common_utility_include_dir' in options: safe_makedirs(options['common_utility_include_dir']) - pythran_options = None - if pythran_version: + if pythran is None: + pythran_options = None + else: pythran_options = CompilationOptions(**options) pythran_options.cplus = True pythran_options.np_pythran = True diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py index 0f1ff4d..dc4add5 100644 --- a/Cython/Compiler/Main.py +++ b/Cython/Compiler/Main.py @@ -38,6 +38,8 @@ module_name_pattern = re.compile(r"[A-Za-z_][A-Za-z0-9_]*(\.[A-Za-z_][A-Za-z0-9_ verbose = 0 +standard_include_path = os.path.abspath(os.path.join(os.path.dirname(__file__), + os.path.pardir, 'Includes')) class CompilationData(object): # Bundles the information that is passed from transform to transform. @@ -88,10 +90,6 @@ class Context(object): self.pxds = {} # full name -> node tree self._interned = {} # (type(value), value, *key_args) -> interned_value - standard_include_path = os.path.abspath(os.path.normpath( - os.path.join(os.path.dirname(__file__), os.path.pardir, 'Includes'))) - self.include_directories = include_directories + [standard_include_path] - if language_level is not None: self.set_language_level(language_level) @@ -99,18 +97,17 @@ class Context(object): def set_language_level(self, level): from .Future import print_function, unicode_literals, absolute_import, division - future_directives = [] + future_directives = set() if level == '3str': - future_directives = [print_function, absolute_import, division] - self.future_directives.discard(unicode_literals) level = 3 else: level = int(level) if level >= 3: - future_directives = [print_function, unicode_literals, absolute_import, division] + future_directives.add(unicode_literals) + if level >= 3: + future_directives.update([print_function, absolute_import, division]) self.language_level = level - if future_directives: - self.future_directives.update(future_directives) + self.future_directives = future_directives if level >= 3: self.modules['builtins'] = self.modules['__builtin__'] @@ -290,8 +287,13 @@ class Context(object): def search_include_directories(self, qualified_name, suffix, pos, include=False, sys_path=False): - return Utils.search_include_directories( - tuple(self.include_directories), qualified_name, suffix, pos, include, sys_path) + include_dirs = self.include_directories + if sys_path: + include_dirs = include_dirs + sys.path + # include_dirs must be hashable for caching in @cached_function + include_dirs = tuple(include_dirs + [standard_include_path]) + return search_include_directories(include_dirs, qualified_name, + suffix, pos, include) def find_root_package_dir(self, file_path): return Utils.find_root_package_dir(file_path) @@ -778,6 +780,56 @@ def compile(source, options = None, full_module_name = None, **kwds): return compile_multiple(source, options) +@Utils.cached_function +def search_include_directories(dirs, qualified_name, suffix, pos, include=False): + """ + Search the list of include directories for the given file name. + + If a source file position is given, first searches the directory + containing that file. Returns None if not found, but does not + report an error. + + The 'include' option will disable package dereferencing. + """ + + if pos: + file_desc = pos[0] + if not isinstance(file_desc, FileSourceDescriptor): + raise RuntimeError("Only file sources for code supported") + if include: + dirs = (os.path.dirname(file_desc.filename),) + dirs + else: + dirs = (Utils.find_root_package_dir(file_desc.filename),) + dirs + + dotted_filename = qualified_name + if suffix: + dotted_filename += suffix + + if not include: + names = qualified_name.split('.') + package_names = tuple(names[:-1]) + module_name = names[-1] + module_filename = module_name + suffix + package_filename = "__init__" + suffix + + for dirname in dirs: + path = os.path.join(dirname, dotted_filename) + if os.path.exists(path): + return path + + if not include: + package_dir = Utils.check_package_dir(dirname, package_names) + if package_dir is not None: + path = os.path.join(package_dir, module_filename) + if os.path.exists(path): + return path + path = os.path.join(package_dir, module_name, + package_filename) + if os.path.exists(path): + return path + return None + + # ------------------------------------------------------------------------ # # Main command-line entry point diff --git a/Cython/Compiler/ParseTreeTransforms.py b/Cython/Compiler/ParseTreeTransforms.py index 4ff717b..5ba64b4 100644 --- a/Cython/Compiler/ParseTreeTransforms.py +++ b/Cython/Compiler/ParseTreeTransforms.py @@ -2715,9 +2715,12 @@ class CreateClosureClasses(CythonTransform): node.needs_outer_scope = True return + # entry.cname can contain periods (eg. a derived C method of a class). + # We want to use the cname as part of a C struct name, so we replace + # periods with double underscores. as_name = '%s_%s' % ( target_module_scope.next_id(Naming.closure_class_prefix), - node.entry.cname) + node.entry.cname.replace('.','__')) entry = target_module_scope.declare_c_class( name=as_name, pos=node.pos, defining=True, diff --git a/Cython/Compiler/Pythran.py b/Cython/Compiler/Pythran.py index fc81956..7114d70 100644 --- a/Cython/Compiler/Pythran.py +++ b/Cython/Compiler/Pythran.py @@ -8,11 +8,10 @@ import cython try: import pythran - pythran_version = pythran.__version__ - pythran_is_0_8_7 = pythran_version >= '0.9' or pythran_version >= '0.8.7' + pythran_is_pre_0_9 = tuple(map(int, pythran.__version__.split('.')[0:2])) < (0, 9) except ImportError: - pythran_version = None - pythran_is_0_8_7 = False + pythran = None + pythran_is_pre_0_9 = True # Pythran/Numpy specific operations @@ -41,10 +40,10 @@ def pythran_type(Ty, ptype="ndarray"): ctype = dtype.typedef_cname else: raise ValueError("unsupported type %s!" % dtype) - if pythran_is_0_8_7: - return "pythonic::types::%s<%s,pythonic::types::pshape<%s>>" % (ptype,ctype, ",".join(("Py_ssize_t",)*ndim)) - else: + if pythran_is_pre_0_9: return "pythonic::types::%s<%s,%d>" % (ptype,ctype, ndim) + else: + return "pythonic::types::%s<%s,pythonic::types::pshape<%s>>" % (ptype,ctype, ",".join(("Py_ssize_t",)*ndim)) if Ty.is_pythran_expr: return Ty.pythran_type #if Ty.is_none: @@ -82,14 +81,8 @@ def _index_access(index_code, indices): def _index_type_code(index_with_type): idx, index_type = index_with_type if idx.is_slice: - if idx.step.is_none: - func = "contiguous_slice" - n = 2 - else: - func = "slice" - n = 3 - return "pythonic::types::%s(%s)" % ( - func, ",".join(["0"]*n)) + n = 2 + int(not idx.step.is_none) + return "pythonic::__builtin__::functor::slice{}(%s)" % (",".join(["0"]*n)) elif index_type.is_int: return "std::declval<%s>()" % index_type.sign_and_name() elif index_type.is_pythran_expr: @@ -129,7 +122,10 @@ def np_func_to_list(func): return [] return np_func_to_list(func.obj) + [func.attribute] -if pythran_version: +if pythran is None: + def pythran_is_numpy_func_supported(name): + return False +else: def pythran_is_numpy_func_supported(func): CurF = pythran.tables.MODULES['numpy'] FL = np_func_to_list(func) @@ -138,9 +134,6 @@ if pythran_version: if CurF is None: return False return True -else: - def pythran_is_numpy_func_supported(name): - return False def pythran_functor(func): func = np_func_to_list(func) @@ -214,6 +207,7 @@ def include_pythran_generic(env): env.add_include_file("pythonic/types/bool.hpp") env.add_include_file("pythonic/types/ndarray.hpp") env.add_include_file("pythonic/numpy/power.hpp") + env.add_include_file("pythonic/__builtin__/slice.hpp") env.add_include_file("") # for placement new for i in (8, 16, 32, 64): diff --git a/Cython/Debugger/Tests/TestLibCython.py b/Cython/Debugger/Tests/TestLibCython.py index b789b10..1356064 100644 --- a/Cython/Debugger/Tests/TestLibCython.py +++ b/Cython/Debugger/Tests/TestLibCython.py @@ -40,7 +40,7 @@ def test_gdb(): else: stdout, _ = p.communicate() # Based on Lib/test/test_gdb.py - regex = "GNU gdb [^\d]*(\d+)\.(\d+)" + regex = r"GNU gdb [^\d]*(\d+)\.(\d+)" gdb_version = re.match(regex, stdout.decode('ascii', 'ignore')) if gdb_version: diff --git a/Cython/Shadow.py b/Cython/Shadow.py index 08ebfb4..c8820ea 100644 --- a/Cython/Shadow.py +++ b/Cython/Shadow.py @@ -1,7 +1,7 @@ # cython.* namespace for pure mode. from __future__ import absolute_import -__version__ = "0.29.10" +__version__ = "0.29.11" try: from __builtin__ import basestring diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c index 6360215..5df5584 100644 --- a/Cython/Utility/ModuleSetupCode.c +++ b/Cython/Utility/ModuleSetupCode.c @@ -384,6 +384,9 @@ class __Pyx_FakeReference { #if PY_VERSION_HEX < 0x030800A4 #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \ PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) +#elif PY_VERSION_HEX >= 0x030800B2 + #define __Pyx_PyCode_New(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \ + PyCode_NewWithPosOnlyArgs(a, p, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) #else #define __Pyx_PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) \ PyCode_New(a, 0, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos) diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c index 22d1634..d6c32ac 100644 --- a/Cython/Utility/Optimize.c +++ b/Cython/Utility/Optimize.c @@ -685,9 +685,11 @@ static PyObject* __Pyx__PyNumber_PowerOf2(PyObject *two, PyObject *exp, PyObject return PyLong_FromUnsignedLongLong(value); #endif } else { - PyObject *one = PyInt_FromLong(1L); + PyObject *result, *one = PyInt_FromLong(1L); if (unlikely(!one)) return NULL; - return PyNumber_Lshift(one, exp); + result = PyNumber_Lshift(one, exp); + Py_DECREF(one); + return result; } } else if (shiftby == -1 && PyErr_Occurred()) { PyErr_Clear(); diff --git a/Cython/Utils.py b/Cython/Utils.py index 6caf410..380ad4a 100644 --- a/Cython/Utils.py +++ b/Cython/Utils.py @@ -124,54 +124,6 @@ def copy_file_to_dir_if_newer(sourcefile, destdir): @cached_function -def search_include_directories(dirs, qualified_name, suffix, pos, - include=False, sys_path=False): - # Search the list of include directories for the given - # file name. If a source file position is given, first - # searches the directory containing that file. Returns - # None if not found, but does not report an error. - # The 'include' option will disable package dereferencing. - # If 'sys_path' is True, also search sys.path. - if sys_path: - dirs = dirs + tuple(sys.path) - if pos: - file_desc = pos[0] - from Cython.Compiler.Scanning import FileSourceDescriptor - if not isinstance(file_desc, FileSourceDescriptor): - raise RuntimeError("Only file sources for code supported") - if include: - dirs = (os.path.dirname(file_desc.filename),) + dirs - else: - dirs = (find_root_package_dir(file_desc.filename),) + dirs - - dotted_filename = qualified_name - if suffix: - dotted_filename += suffix - if not include: - names = qualified_name.split('.') - package_names = tuple(names[:-1]) - module_name = names[-1] - module_filename = module_name + suffix - package_filename = "__init__" + suffix - - for dir in dirs: - path = os.path.join(dir, dotted_filename) - if path_exists(path): - return path - if not include: - package_dir = check_package_dir(dir, package_names) - if package_dir is not None: - path = os.path.join(package_dir, module_filename) - if path_exists(path): - return path - path = os.path.join(dir, package_dir, module_name, - package_filename) - if path_exists(path): - return path - return None - - -@cached_function def find_root_package_dir(file_path): dir = os.path.dirname(file_path) if file_path == dir: diff --git a/runtests.py b/runtests.py index 646df74..d37f988 100755 --- a/runtests.py +++ b/runtests.py @@ -758,12 +758,10 @@ class TestBuilder(object): pythran_dir = self.pythran_dir if 'pythran' in tags['tag'] and not pythran_dir and 'cpp' in languages: import pythran.config - from pythran import __version__ as pythran_version - pythran_ext = ( - pythran.config.make_extension(python=True) - if pythran_version >= '0.9' or pythran_version >= '0.8.7' - else pythran.config.make_extension() - ) + try: + pythran_ext = pythran.config.make_extension(python=True) + except TypeError: # old pythran version syntax + pythran_ext = pythran.config.make_extension() pythran_dir = pythran_ext['include_dirs'][0] preparse_list = tags.get('preparse', ['id']) diff --git a/tests/compile/find_pxd.srctree b/tests/compile/find_pxd.srctree index 1d7885f..75d2765 100644 --- a/tests/compile/find_pxd.srctree +++ b/tests/compile/find_pxd.srctree @@ -6,12 +6,13 @@ from Cython.Build import cythonize from Cython.Distutils.extension import Extension import sys -sys.path.append("path") +sys.path.insert(0, "path") ext_modules = [ Extension("a", ["a.pyx"]), Extension("b", ["b.pyx"]), Extension("c", ["c.pyx"]), + Extension("d", ["d.pyx"]), ] ext_modules = cythonize(ext_modules, include_path=["include"]) @@ -37,3 +38,15 @@ ctypedef int my_type ######## path/c.pxd ######## +++syntax error just to show that this file is not actually cimported+++ + +######## path/numpy/__init__.pxd ######## + +# gh-2905: This should be found before Cython/Inlude/numpy/__init__.pxd + +ctypedef int my_type + +######## d.pyx ######## + +cimport numpy + +cdef numpy.my_type foo diff --git a/tests/run/closure_in_derived_class_T2967.pyx b/tests/run/closure_in_derived_class_T2967.pyx new file mode 100644 index 0000000..d75c5e5 --- /dev/null +++ b/tests/run/closure_in_derived_class_T2967.pyx @@ -0,0 +1,18 @@ +# mode: run +# tag: closures +# ticket: 2967 + +cdef class BaseClass: + cdef func(self): + pass +cdef class ClosureInsideExtensionClass(BaseClass): + """ + >>> y = ClosureInsideExtensionClass(42) + >>> y.test(42) + 43 + """ + cdef func(self): + a = 1 + return (lambda x : x+a) + def test(self, b): + return self.func()(b) diff --git a/tests/run/language_level.srctree b/tests/run/language_level.srctree index 9162498..5e9ab64 100644 --- a/tests/run/language_level.srctree +++ b/tests/run/language_level.srctree @@ -7,12 +7,19 @@ PYTHON -c "import infile2; import infile3" from Cython.Build.Dependencies import cythonize from distutils.core import setup -setup( - ext_modules = (cythonize("infile*.py") + - cythonize("directive2.py", compiler_directives={'language_level': 2}) + - cythonize("directive3.py", compiler_directives={'language_level': 3}) - ) -) +ext_modules = [] + +# Test language_level specified in the cythonize() call +ext_modules += cythonize("directive2.py", compiler_directives={'language_level': 2}) +ext_modules += cythonize("directive3.py", compiler_directives={'language_level': 3}) + +# Test language_level specified in the source file. We give a +# conflicting directive to cythonize() to check that the language_level +# is correctly overridden when compiling +ext_modules += cythonize("infile2.py", compiler_directives={'language_level': 3}) +ext_modules += cythonize("infile3.py", compiler_directives={'language_level': 2}) + +setup(ext_modules=ext_modules) ######## directive3.py ########