Hello community, here is the log from the commit of package python-Cython for openSUSE:Factory checked in at 2020-04-22 20:41:58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-Cython (Old) and /work/SRC/openSUSE:Factory/.python-Cython.new.2738 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-Cython" Wed Apr 22 20:41:58 2020 rev:53 rq:794812 version:0.29.16 Changes: -------- --- /work/SRC/openSUSE:Factory/python-Cython/python-Cython.changes 2020-02-22 19:02:51.397920314 +0100 +++ /work/SRC/openSUSE:Factory/.python-Cython.new.2738/python-Cython.changes 2020-04-22 20:42:07.346115404 +0200 @@ -1,0 +2,36 @@ +Fri Apr 17 08:10:03 UTC 2020 - Marketa Calabkova <[email protected]> + +- update to 0.29.16 + * Temporary internal variables in nested prange loops could leak into other + threads. Patch by Frank Schlimbach. (Github issue #3348) + * Default arguments on fused functions could crash. + Patch by David Woods. (Github issue #3370) + * C-tuples declared in ``.pxd`` files could generate incomplete C code. + Patch by Kirk Meyer. (Github issue #1427) + * Fused functions were not always detected and optimised as Cython + implemented functions. + Patch by David Woods. (Github issue #3384) + * Valid Python object concatenation of (iterable) strings to non-strings + could fail with an exception. + Patch by David Woods. (Github issue #3433) + * Using C functions as temporary values lead to invalid C code. + Original patch by David Woods. (Github issue #3418) + * Fix an unhandled C++ exception in comparisons. + Patch by David Woods. (Github issue #3361) + * Fix deprecated import of "imp" module. + Patch by Matti Picus. (Github issue #3350) + * Fix compatibility with Pythran 0.9.6 and later. + Patch by Serge Guelton. (Github issue #3308) + * The ``_Py_PyAtExit()`` function in ``cpython.pylifecycle`` was misdeclared. + Patch by Zackery Spytz. (Github issue #3382) + * Several missing declarations in ``cpython.*`` were added. + Patches by Zackery Spytz. (Github issue #3452, #3421, #3411, #3402) + * A declaration for ``libc.math.fpclassify()`` was added. + Patch by Zackery Spytz. (Github issue #2514) + * Avoid "undeclared" warning about automatically generated pickle methods. + Patch by David Woods. (Github issue #3353) + * Avoid C compiler warning about unreachable code in ``prange()``. + * Some C compiler warnings in PyPy were resolved. + Patch by Matti Picus. (Github issue #3437) + +------------------------------------------------------------------- Old: ---- Cython-0.29.15.tar.gz New: ---- Cython-0.29.16.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-Cython.spec ++++++ --- /var/tmp/diff_new_pack.MrXK4U/_old 2020-04-22 20:42:08.702118058 +0200 +++ /var/tmp/diff_new_pack.MrXK4U/_new 2020-04-22 20:42:08.706118067 +0200 @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %define oldpython python Name: python-Cython -Version: 0.29.15 +Version: 0.29.16 Release: 0 Summary: The Cython compiler for writing C extensions for the Python language License: Apache-2.0 ++++++ Cython-0.29.15.tar.gz -> Cython-0.29.16.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/.gitrev new/Cython-0.29.16/.gitrev --- old/Cython-0.29.15/.gitrev 2020-02-06 11:27:36.000000000 +0100 +++ new/Cython-0.29.16/.gitrev 2020-03-24 15:54:53.000000000 +0100 @@ -1 +1 @@ -26cb654dcf4ed1b1858daf16b39fd13406b1ac64 +c8425604fc3e4ea846016689942fa98e886b5f4f diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/CHANGES.rst new/Cython-0.29.16/CHANGES.rst --- old/Cython-0.29.15/CHANGES.rst 2020-02-06 11:26:34.000000000 +0100 +++ new/Cython-0.29.16/CHANGES.rst 2020-03-24 15:54:39.000000000 +0100 @@ -2,9 +2,65 @@ Cython Changelog ================ +0.29.16 (2020-03-24) +==================== + +Bugs fixed +---------- + +* Temporary internal variables in nested prange loops could leak into other + threads. Patch by Frank Schlimbach. (Github issue #3348) + +* Default arguments on fused functions could crash. + Patch by David Woods. (Github issue #3370) + +* C-tuples declared in ``.pxd`` files could generate incomplete C code. + Patch by Kirk Meyer. (Github issue #1427) + +* Fused functions were not always detected and optimised as Cython + implemented functions. + Patch by David Woods. (Github issue #3384) + +* Valid Python object concatenation of (iterable) strings to non-strings + could fail with an exception. + Patch by David Woods. (Github issue #3433) + +* Using C functions as temporary values lead to invalid C code. + Original patch by David Woods. (Github issue #3418) + +* Fix an unhandled C++ exception in comparisons. + Patch by David Woods. (Github issue #3361) + +* Fix deprecated import of "imp" module. + Patch by Matti Picus. (Github issue #3350) + +* Fix compatibility with Pythran 0.9.6 and later. + Patch by Serge Guelton. (Github issue #3308) + +* The ``_Py_PyAtExit()`` function in ``cpython.pylifecycle`` was misdeclared. + Patch by Zackery Spytz. (Github issue #3382) + +* Several missing declarations in ``cpython.*`` were added. + Patches by Zackery Spytz. (Github issue #3452, #3421, #3411, #3402) + +* A declaration for ``libc.math.fpclassify()`` was added. + Patch by Zackery Spytz. (Github issue #2514) + +* Avoid "undeclared" warning about automatically generated pickle methods. + Patch by David Woods. (Github issue #3353) + +* Avoid C compiler warning about unreachable code in ``prange()``. + +* Some C compiler warnings in PyPy were resolved. + Patch by Matti Picus. (Github issue #3437) + + 0.29.15 (2020-02-06) ==================== +Bugs fixed +---------- + * Crash when returning a temporary Python object from an async-def function. (Github issue #3337) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Build/Dependencies.py new/Cython-0.29.16/Cython/Build/Dependencies.py --- old/Cython-0.29.15/Cython/Build/Dependencies.py 2020-02-06 11:26:34.000000000 +0100 +++ new/Cython-0.29.16/Cython/Build/Dependencies.py 2020-03-24 15:54:39.000000000 +0100 @@ -910,7 +910,8 @@ variable called ``foo`` as a string, and then call ``cythonize(..., aliases={'MY_HEADERS': foo})``. - :param quiet: If True, Cython won't print error and warning messages during the compilation. + :param quiet: If True, Cython won't print error, warning, or status messages during the + compilation. :param force: Forces the recompilation of the Cython modules, even if the timestamps don't indicate that a recompilation is necessary. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Build/Inline.py new/Cython-0.29.16/Cython/Build/Inline.py --- old/Cython-0.29.15/Cython/Build/Inline.py 2019-05-27 21:37:21.000000000 +0200 +++ new/Cython-0.29.16/Cython/Build/Inline.py 2020-03-24 15:54:39.000000000 +0100 @@ -35,6 +35,14 @@ else: to_unicode = lambda x: x +if sys.version_info[:2] < (3, 3): + import imp + def load_dynamic(name, module_path): + return imp.load_dynamic(name, module_path) +else: + from importlib.machinery import ExtensionFileLoader + def load_dynamic(name, module_path): + return ExtensionFileLoader(name, module_path).load_module() class UnboundSymbols(EnvTransform, SkipDeclarations): def __init__(self): @@ -249,7 +257,7 @@ build_extension.build_lib = lib_dir build_extension.run() - module = imp.load_dynamic(module_name, module_path) + module = load_dynamic(module_name, module_path) _cython_inline_cache[orig_code, arg_sigs] = module.__invoke arg_list = [kwds[arg] for arg in arg_names] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Compiler/Code.py new/Cython-0.29.16/Cython/Compiler/Code.py --- old/Cython-0.29.15/Cython/Compiler/Code.py 2019-07-07 10:37:19.000000000 +0200 +++ new/Cython-0.29.16/Cython/Compiler/Code.py 2020-03-24 15:54:39.000000000 +0100 @@ -832,6 +832,9 @@ type = type.const_base_type elif type.is_reference and not type.is_fake_reference: type = type.ref_base_type + elif type.is_cfunction: + from . import PyrexTypes + type = PyrexTypes.c_ptr_type(type) # A function itself isn't an l-value if not type.is_pyobject and not type.is_memoryviewslice: # Make manage_ref canonical, so that manage_ref will always mean # a decref is needed. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Compiler/ExprNodes.py new/Cython-0.29.16/Cython/Compiler/ExprNodes.py --- old/Cython-0.29.15/Cython/Compiler/ExprNodes.py 2020-02-06 11:26:34.000000000 +0100 +++ new/Cython-0.29.16/Cython/Compiler/ExprNodes.py 2020-03-24 15:54:39.000000000 +0100 @@ -11390,19 +11390,24 @@ self, type1, type2) def py_operation_function(self, code): - is_unicode_concat = False - if isinstance(self.operand1, FormattedValueNode) or isinstance(self.operand2, FormattedValueNode): - is_unicode_concat = True - else: - type1, type2 = self.operand1.type, self.operand2.type - if type1 is unicode_type or type2 is unicode_type: - is_unicode_concat = type1.is_builtin_type and type2.is_builtin_type - - if is_unicode_concat: - if self.operand1.may_be_none() or self.operand2.may_be_none(): - return '__Pyx_PyUnicode_ConcatSafe' + type1, type2 = self.operand1.type, self.operand2.type + + if type1 is unicode_type or type2 is unicode_type: + if type1 in (unicode_type, str_type) and type2 in (unicode_type, str_type): + is_unicode_concat = True + elif isinstance(self.operand1, FormattedValueNode) or isinstance(self.operand2, FormattedValueNode): + # Assume that even if we don't know the second type, it's going to be a string. + is_unicode_concat = True else: - return '__Pyx_PyUnicode_Concat' + # Operation depends on the second type. + is_unicode_concat = False + + if is_unicode_concat: + if self.operand1.may_be_none() or self.operand2.may_be_none(): + return '__Pyx_PyUnicode_ConcatSafe' + else: + return '__Pyx_PyUnicode_Concat' + return super(AddNode, self).py_operation_function(code) @@ -12485,7 +12490,8 @@ result_code if self.type.is_pyobject else None, self.exception_value, self.in_nogil_context) - code.putln(statement) + else: + code.putln(statement) def c_operator(self, op): if op == 'is': diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Compiler/ModuleNode.py new/Cython-0.29.16/Cython/Compiler/ModuleNode.py --- old/Cython-0.29.15/Cython/Compiler/ModuleNode.py 2019-11-01 15:13:39.000000000 +0100 +++ new/Cython-0.29.16/Cython/Compiler/ModuleNode.py 2020-03-24 15:54:39.000000000 +0100 @@ -575,15 +575,17 @@ for entry in vtabslot_list: self.generate_objstruct_predeclaration(entry.type, code) vtabslot_entries = set(vtabslot_list) + ctuple_names = set() for module in modules: definition = module is env - if definition: - type_entries = module.type_entries - else: - type_entries = [] - for entry in module.type_entries: - if entry.defined_in_pxd: + type_entries = [] + for entry in module.type_entries: + if entry.type.is_ctuple: + if entry.name not in ctuple_names: + ctuple_names.add(entry.name) type_entries.append(entry) + elif definition or entry.defined_in_pxd: + type_entries.append(entry) type_entries = [t for t in type_entries if t not in vtabslot_entries] self.generate_type_header_code(type_entries, code) for entry in vtabslot_list: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Compiler/Nodes.py new/Cython-0.29.16/Cython/Compiler/Nodes.py --- old/Cython-0.29.15/Cython/Compiler/Nodes.py 2020-02-06 11:26:34.000000000 +0100 +++ new/Cython-0.29.16/Cython/Compiler/Nodes.py 2020-03-24 15:54:39.000000000 +0100 @@ -9119,7 +9119,7 @@ # TODO: check if the step is 0 and if so, raise an exception in a # 'with gil' block. For now, just abort - code.putln("if (%(step)s == 0) abort();" % fmt_dict) + code.putln("if ((%(step)s == 0)) abort();" % fmt_dict) self.setup_parallel_control_flow_block(code) # parallel control flow block @@ -9240,12 +9240,15 @@ code.putln("%(target)s = (%(target_type)s)(%(start)s + %(step)s * %(i)s);" % fmt_dict) self.initialize_privates_to_nan(code, exclude=self.target.entry) - if self.is_parallel: + if self.is_parallel and not self.is_nested_prange: + # nested pranges are not omp'ified, temps go to outer loops code.funcstate.start_collecting_temps() self.body.generate_execution_code(code) self.trap_parallel_exit(code, should_flush=True) - self.privatize_temps(code) + if self.is_parallel and not self.is_nested_prange: + # nested pranges are not omp'ified, temps go to outer loops + self.privatize_temps(code) if self.breaking_label_used: # Put a guard around the loop body in case return, break or diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Compiler/ParseTreeTransforms.py new/Cython-0.29.16/Cython/Compiler/ParseTreeTransforms.py --- old/Cython-0.29.15/Cython/Compiler/ParseTreeTransforms.py 2019-06-30 08:50:51.000000000 +0200 +++ new/Cython-0.29.16/Cython/Compiler/ParseTreeTransforms.py 2020-03-24 15:54:39.000000000 +0100 @@ -1763,7 +1763,9 @@ }, level='c_class', pipeline=[NormalizeTree(None)]).substitute({}) pickle_func.analyse_declarations(node.scope) + self.enter_scope(node, node.scope) # functions should be visited in the class scope self.visit(pickle_func) + self.exit_scope() node.body.stats.append(pickle_func) def _handle_fused_def_decorators(self, old_decorators, env, node): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Compiler/Pythran.py new/Cython-0.29.16/Cython/Compiler/Pythran.py --- old/Cython-0.29.15/Cython/Compiler/Pythran.py 2019-07-07 10:37:19.000000000 +0200 +++ new/Cython-0.29.16/Cython/Compiler/Pythran.py 2020-03-24 15:54:39.000000000 +0100 @@ -9,9 +9,16 @@ try: import pythran pythran_is_pre_0_9 = tuple(map(int, pythran.__version__.split('.')[0:2])) < (0, 9) + pythran_is_pre_0_9_6 = tuple(map(int, pythran.__version__.split('.')[0:3])) < (0, 9, 6) except ImportError: pythran = None pythran_is_pre_0_9 = True + pythran_is_pre_0_9_6 = True + +if pythran_is_pre_0_9_6: + pythran_builtins = '__builtin__' +else: + pythran_builtins = 'builtins' # Pythran/Numpy specific operations @@ -47,7 +54,7 @@ if Ty.is_pythran_expr: return Ty.pythran_type #if Ty.is_none: - # return "decltype(pythonic::__builtin__::None)" + # return "decltype(pythonic::builtins::None)" if Ty.is_numeric: return Ty.sign_and_name() raise ValueError("unsupported pythran type %s (%s)" % (Ty, type(Ty))) @@ -82,7 +89,9 @@ idx, index_type = index_with_type if idx.is_slice: n = 2 + int(not idx.step.is_none) - return "pythonic::__builtin__::functor::slice{}(%s)" % (",".join(["0"]*n)) + return "pythonic::%s::functor::slice{}(%s)" % ( + pythran_builtins, + ",".join(["0"]*n)) elif index_type.is_int: return "std::declval<%s>()" % index_type.sign_and_name() elif index_type.is_pythran_expr: @@ -154,7 +163,7 @@ if is_type(op_type, ["is_pythran_expr", "is_numeric", "is_float", "is_complex"]): return op.result() if op.is_none: - return "pythonic::__builtin__::None" + return "pythonic::%s::None" % pythran_builtins if ptype is None: ptype = pythran_type(op_type) @@ -207,7 +216,7 @@ 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("pythonic/%s/slice.hpp" % pythran_builtins) env.add_include_file("<new>") # for placement new for i in (8, 16, 32, 64): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Includes/cpython/genobject.pxd new/Cython-0.29.16/Cython/Includes/cpython/genobject.pxd --- old/Cython-0.29.15/Cython/Includes/cpython/genobject.pxd 1970-01-01 01:00:00.000000000 +0100 +++ new/Cython-0.29.16/Cython/Includes/cpython/genobject.pxd 2020-03-24 15:54:39.000000000 +0100 @@ -0,0 +1,25 @@ +from .pystate cimport PyFrameObject + +cdef extern from "Python.h": + + ########################################################################### + # Generator Objects + ########################################################################### + + bint PyGen_Check(object ob) + # Return true if ob is a generator object; ob must not be NULL. + + bint PyGen_CheckExact(object ob) + # Return true if ob's type is PyGen_Type; ob must not be NULL. + + object PyGen_New(PyFrameObject *frame) + # Return value: New reference. + # Create and return a new generator object based on the frame object. A + # reference to frame is stolen by this function. The argument must not be + # NULL. + + object PyGen_NewWithQualName(PyFrameObject *frame, object name, object qualname) + # Return value: New reference. + # Create and return a new generator object based on the frame object, with + # __name__ and __qualname__ set to name and qualname. A reference to frame + # is stolen by this function. The frame argument must not be NULL. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Includes/cpython/iterobject.pxd new/Cython-0.29.16/Cython/Includes/cpython/iterobject.pxd --- old/Cython-0.29.15/Cython/Includes/cpython/iterobject.pxd 1970-01-01 01:00:00.000000000 +0100 +++ new/Cython-0.29.16/Cython/Includes/cpython/iterobject.pxd 2020-03-24 15:54:39.000000000 +0100 @@ -0,0 +1,24 @@ +cdef extern from "Python.h": + + ########################################################################### + # Iterator Objects + ########################################################################### + + bint PySeqIter_Check(object op) + # Return true if the type of op is PySeqIter_Type. + + object PySeqIter_New(object seq) + # Return value: New reference. + # Return an iterator that works with a general sequence object, seq. The + # iteration ends when the sequence raises IndexError for the subscripting + # operation. + + bint PyCallIter_Check(object op) + # Return true if the type of op is PyCallIter_Type. + + object PyCallIter_New(object callable, object sentinel) + # Return value: New reference. + # Return a new iterator. The first parameter, callable, can be any Python + # callable object that can be called with no parameters; each call to it + # should return the next item in the iteration. When callable returns a + # value equal to sentinel, the iteration will be terminated. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Includes/cpython/number.pxd new/Cython-0.29.16/Cython/Includes/cpython/number.pxd --- old/Cython-0.29.15/Cython/Includes/cpython/number.pxd 2015-06-22 14:53:11.000000000 +0200 +++ new/Cython-0.29.16/Cython/Includes/cpython/number.pxd 2020-03-24 15:54:39.000000000 +0100 @@ -27,6 +27,13 @@ # failure. This is the equivalent of the Python expression "o1 * # o2". + object PyNumber_MatrixMultiply(object o1, object o2) + # Return value: New reference. + # Returns the result of matrix multiplication on o1 and o2, or + # NULL on failure. This is the equivalent of the Python + # expression "o1 @ o2". + # New in version 3.5. + object PyNumber_Divide(object o1, object o2) # Return value: New reference. # Returns the result of dividing o1 by o2, or NULL on @@ -133,6 +140,13 @@ # failure. The operation is done in-place when o1 supports # it. This is the equivalent of the Python statement "o1 *= o2". + object PyNumber_InPlaceMatrixMultiply(object o1, object o2) + # Return value: New reference. + # Returns the result of matrix multiplication on o1 and o2, or + # NULL on failure. The operation is done in-place when o1 supports + # it. This is the equivalent of the Python statement "o1 @= o2". + # New in version 3.5. + object PyNumber_InPlaceDivide(object o1, object o2) # Return value: New reference. # Returns the result of dividing o1 by o2, or NULL on failure. The diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Includes/cpython/pylifecycle.pxd new/Cython-0.29.16/Cython/Includes/cpython/pylifecycle.pxd --- old/Cython-0.29.15/Cython/Includes/cpython/pylifecycle.pxd 2018-11-24 10:20:06.000000000 +0100 +++ new/Cython-0.29.16/Cython/Includes/cpython/pylifecycle.pxd 2020-03-24 15:54:39.000000000 +0100 @@ -27,9 +27,9 @@ void Py_EndInterpreter(PyThreadState *) - # Py_PyAtExit is for the atexit module, Py_AtExit is for low-level + # _Py_PyAtExit is for the atexit module, Py_AtExit is for low-level # exit functions. - void _Py_PyAtExit(void (*func)()) + void _Py_PyAtExit(void (*func)(object), object) int Py_AtExit(void (*func)()) void Py_Exit(int) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Includes/cpython/slice.pxd new/Cython-0.29.16/Cython/Includes/cpython/slice.pxd --- old/Cython-0.29.15/Cython/Includes/cpython/slice.pxd 2015-06-22 14:53:11.000000000 +0200 +++ new/Cython-0.29.16/Cython/Includes/cpython/slice.pxd 2020-03-24 15:54:39.000000000 +0100 @@ -45,3 +45,26 @@ # # Changed in version 3.2: The parameter type for the slice parameter was # PySliceObject* before. + + int PySlice_Unpack(object slice, Py_ssize_t *start, Py_ssize_t *stop, + Py_ssize_t *step) except -1 + # Extract the start, stop and step data members from a slice object as C + # integers. Silently reduce values larger than PY_SSIZE_T_MAX to + # PY_SSIZE_T_MAX, silently boost the start and stop values less than + # PY_SSIZE_T_MIN to PY_SSIZE_T_MIN, and silently boost the step values + # less than -PY_SSIZE_T_MAX to -PY_SSIZE_T_MAX. + + # Return -1 on error, 0 on success. + + # New in version 3.6.1. + + Py_ssize_t PySlice_AdjustIndices(Py_ssize_t length, Py_ssize_t *start, + Py_ssize_t *stop, Py_ssize_t step) + # Adjust start/end slice indices assuming a sequence of the specified + # length. Out of bounds indices are clipped in a manner consistent with + # the handling of normal slices. + + # Return the length of the slice. Always successful. Doesn’t call Python + # code. + + # New in version 3.6.1. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Includes/libc/math.pxd new/Cython-0.29.16/Cython/Includes/libc/math.pxd --- old/Cython-0.29.15/Cython/Includes/libc/math.pxd 2018-11-24 10:20:06.000000000 +0100 +++ new/Cython-0.29.16/Cython/Includes/libc/math.pxd 2020-03-24 15:54:39.000000000 +0100 @@ -104,3 +104,9 @@ bint isnan(long double) bint isnormal(long double) bint signbit(long double) + int fpclassify(long double) + const int FP_NAN + const int FP_INFINITE + const int FP_ZERO + const int FP_SUBNORMAL + const int FP_NORMAL diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Shadow.py new/Cython-0.29.16/Cython/Shadow.py --- old/Cython-0.29.15/Cython/Shadow.py 2020-02-06 11:26:34.000000000 +0100 +++ new/Cython-0.29.16/Cython/Shadow.py 2020-03-24 15:54:39.000000000 +0100 @@ -1,7 +1,7 @@ # cython.* namespace for pure mode. from __future__ import absolute_import -__version__ = "0.29.15" +__version__ = "0.29.16" try: from __builtin__ import basestring diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Utility/CythonFunction.c new/Cython-0.29.16/Cython/Utility/CythonFunction.c --- old/Cython-0.29.15/Cython/Utility/CythonFunction.c 2019-11-01 15:13:39.000000000 +0100 +++ new/Cython-0.29.16/Cython/Utility/CythonFunction.c 2020-03-24 15:54:39.000000000 +0100 @@ -36,6 +36,7 @@ // Dynamic default args and annotations void *defaults; int defaults_pyobjects; + size_t defaults_size; // used by FusedFunction for copying defaults int flags; // Defaults info @@ -471,6 +472,7 @@ op->func_code = code; // Dynamic Default args op->defaults_pyobjects = 0; + op->defaults_size = 0; op->defaults = NULL; op->defaults_tuple = NULL; op->defaults_kwdict = NULL; @@ -755,6 +757,7 @@ return PyErr_NoMemory(); memset(m->defaults, 0, size); m->defaults_pyobjects = pyobjects; + m->defaults_size = size; return m->defaults; } @@ -904,6 +907,26 @@ if (!meth) return NULL; + // defaults needs copying fully rather than just copying the pointer + // since otherwise it will be freed on destruction of meth despite + // belonging to func rather than meth + if (func->func.defaults) { + PyObject **pydefaults; + int i; + + if (!__Pyx_CyFunction_InitDefaults((PyObject*)meth, + func->func.defaults_size, + func->func.defaults_pyobjects)) { + Py_XDECREF((PyObject*)meth); + return NULL; + } + memcpy(meth->func.defaults, func->func.defaults, func->func.defaults_size); + + pydefaults = __Pyx_CyFunction_Defaults(PyObject *, meth); + for (i = 0; i < meth->func.defaults_pyobjects; i++) + Py_XINCREF(pydefaults[i]); + } + Py_XINCREF(func->func.func_classobj); meth->func.func_classobj = func->func.func_classobj; @@ -1189,6 +1212,7 @@ // __doc__ is None for the fused function type, but we need it to be // a descriptor for the instance's __doc__, so rebuild descriptors in our subclass __pyx_CyFunction_getsets, /*tp_getset*/ + // NOTE: tp_base may be changed later during module initialisation when importing CyFunction across modules. &__pyx_CyFunctionType_type, /*tp_base*/ 0, /*tp_dict*/ __pyx_FusedFunction_descr_get, /*tp_descr_get*/ @@ -1218,6 +1242,8 @@ }; static int __pyx_FusedFunction_init(void) { + // Set base from __Pyx_FetchCommonTypeFromSpec, in case it's different from the local static value. + __pyx_FusedFunctionType_type.tp_base = __pyx_CyFunctionType; __pyx_FusedFunctionType = __Pyx_FetchCommonType(&__pyx_FusedFunctionType_type); if (__pyx_FusedFunctionType == NULL) { return -1; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Utility/Exceptions.c new/Cython-0.29.16/Cython/Utility/Exceptions.c --- old/Cython-0.29.15/Cython/Utility/Exceptions.c 2019-02-08 20:14:39.000000000 +0100 +++ new/Cython-0.29.16/Cython/Utility/Exceptions.c 2020-03-24 15:54:39.000000000 +0100 @@ -647,7 +647,7 @@ //@substitute: naming #ifndef CYTHON_CLINE_IN_TRACEBACK -static int __Pyx_CLineForTraceback(PyThreadState *tstate, int c_line) { +static int __Pyx_CLineForTraceback(CYTHON_NCP_UNUSED PyThreadState *tstate, int c_line) { PyObject *use_cline; PyObject *ptype, *pvalue, *ptraceback; #if CYTHON_COMPILING_IN_CPYTHON diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Cython/Utility/ModuleSetupCode.c new/Cython-0.29.16/Cython/Utility/ModuleSetupCode.c --- old/Cython-0.29.15/Cython/Utility/ModuleSetupCode.c 2019-07-07 10:37:19.000000000 +0200 +++ new/Cython-0.29.16/Cython/Utility/ModuleSetupCode.c 2020-03-24 15:54:39.000000000 +0100 @@ -591,8 +591,11 @@ #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact + // PyPy3 used to define "PyObject_Unicode" +#ifndef PyObject_Unicode #define PyObject_Unicode PyObject_Str #endif +#endif #if PY_MAJOR_VERSION >= 3 #define __Pyx_PyBaseString_Check(obj) PyUnicode_Check(obj) @@ -1065,7 +1068,7 @@ if (__pyx_code_cache.count == __pyx_code_cache.max_count) { int new_max = __pyx_code_cache.max_count + 64; entries = (__Pyx_CodeObjectCacheEntry*)PyMem_Realloc( - __pyx_code_cache.entries, (size_t)new_max*sizeof(__Pyx_CodeObjectCacheEntry)); + __pyx_code_cache.entries, ((size_t)new_max) * sizeof(__Pyx_CodeObjectCacheEntry)); if (unlikely(!entries)) { return; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/Makefile new/Cython-0.29.16/Makefile --- old/Cython-0.29.15/Makefile 2018-11-24 10:20:06.000000000 +0100 +++ new/Cython-0.29.16/Makefile 2020-03-24 15:54:39.000000000 +0100 @@ -17,6 +17,12 @@ dist/$(PACKAGENAME)-$(VERSION).tar.gz: $(PYTHON) setup.py sdist +pywheel: dist/$(PACKAGENAME)-$(VERSION)-py2.py3-none-any.whl + +dist/$(PACKAGENAME)-$(VERSION)-py2.py3-none-any.whl: + ${PYTHON} setup.py bdist_wheel --no-cython-compile --universal + [ -f "$@" ] # check that we generated the expected universal wheel + TMPDIR = .repo_tmp .git: .gitrev rm -rf $(TMPDIR) @@ -26,6 +32,7 @@ rm -rf $(TMPDIR) git ls-files -d | xargs git checkout -- +# Create a git repo from an unpacked source directory. repo: .git diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/PKG-INFO new/Cython-0.29.16/PKG-INFO --- old/Cython-0.29.15/PKG-INFO 2020-02-06 11:27:44.000000000 +0100 +++ new/Cython-0.29.16/PKG-INFO 2020-03-24 15:55:01.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.2 Name: Cython -Version: 0.29.15 +Version: 0.29.16 Summary: The Cython compiler for writing C extensions for the Python language. Home-page: http://cython.org/ Author: Robert Bradshaw, Stefan Behnel, Dag Seljebotn, Greg Ewing, et al. @@ -42,6 +42,7 @@ Classifier: Programming Language :: Python :: 3.5 Classifier: Programming Language :: Python :: 3.6 Classifier: Programming Language :: Python :: 3.7 +Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Programming Language :: C diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/README.rst new/Cython-0.29.16/README.rst --- old/Cython-0.29.15/README.rst 2018-11-24 10:20:06.000000000 +0100 +++ new/Cython-0.29.16/README.rst 2020-03-24 15:54:39.000000000 +0100 @@ -51,8 +51,9 @@ Note that Cython used to ship the full version control repository in its source distribution, but no longer does so due to space constraints. To get the -full source history, make sure you have git installed, then step into the -base directory of the Cython source distribution and type:: +full source history from a downloaded source archive, make sure you have git +installed, then step into the base directory of the Cython source distribution +and type:: make repo diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/docs/src/tutorial/strings.rst new/Cython-0.29.16/docs/src/tutorial/strings.rst --- old/Cython-0.29.15/docs/src/tutorial/strings.rst 2018-11-24 10:20:06.000000000 +0100 +++ new/Cython-0.29.16/docs/src/tutorial/strings.rst 2020-03-24 15:54:39.000000000 +0100 @@ -220,14 +220,15 @@ .. literalinclude:: ../../examples/tutorial/string/return_memview.pyx -If the byte input is actually encoded text, and the further processing -should happen at the Unicode level, then the right thing to do is to -decode the input straight away. This is almost only a problem in Python -2.x, where Python code expects that it can pass a byte string (:obj:`str`) -with encoded text into a text API. Since this usually happens in more -than one place in the module's API, a helper function is almost always the -way to go, since it allows for easy adaptation of the input normalisation -process later. +For read-only buffers, like :obj:`bytes`, the memoryview item type should +be declared as ``const`` (see :ref:`readonly_views`). If the byte input is +actually encoded text, and the further processing should happen at the +Unicode level, then the right thing to do is to decode the input straight +away. This is almost only a problem in Python 2.x, where Python code +expects that it can pass a byte string (:obj:`str`) with encoded text into +a text API. Since this usually happens in more than one place in the +module's API, a helper function is almost always the way to go, since it +allows for easy adaptation of the input normalisation process later. This kind of input normalisation function will commonly look similar to the following: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/docs/src/userguide/memoryviews.rst new/Cython-0.29.16/docs/src/userguide/memoryviews.rst --- old/Cython-0.29.15/docs/src/userguide/memoryviews.rst 2018-11-24 10:20:06.000000000 +0100 +++ new/Cython-0.29.16/docs/src/userguide/memoryviews.rst 2020-03-24 15:54:39.000000000 +0100 @@ -155,6 +155,9 @@ One may mix new axis indexing with all other forms of indexing and slicing. See also an example_. + +.. _readonly_views: + Read-only views --------------- diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/setup.cfg new/Cython-0.29.16/setup.cfg --- old/Cython-0.29.15/setup.cfg 1970-01-01 01:00:00.000000000 +0100 +++ new/Cython-0.29.16/setup.cfg 2020-02-13 18:26:02.000000000 +0100 @@ -0,0 +1,28 @@ +[flake8] +max-complexity = 10 + +[pycodestyle] +exclude = .git,build,__pycache__,venv*,TEST* +max-line-length = 150 +format = pylint +select = E711, E714, E501, W291 +#ignore = W, E +ignore = + W504, + # W504 line break after binary operator + S001, + # S001 found module formatter + E226, + # E226 missing whitespace around operator[run] + +[coverage:run] +branch = True +parallel = True +concurrency = multiprocessing,thread +include = Cython/* +source = Cython +omit = Test* + +[bdist_wheel] +universal = 1 + diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/setup.py new/Cython-0.29.16/setup.py --- old/Cython-0.29.15/setup.py 2018-11-24 10:20:06.000000000 +0100 +++ new/Cython-0.29.16/setup.py 2020-03-24 15:54:39.000000000 +0100 @@ -270,6 +270,7 @@ "Programming Language :: Python :: 3.5", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", "Programming Language :: Python :: Implementation :: CPython", "Programming Language :: Python :: Implementation :: PyPy", "Programming Language :: C", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/compile/ctuple_cimport.pxd new/Cython-0.29.16/tests/compile/ctuple_cimport.pxd --- old/Cython-0.29.15/tests/compile/ctuple_cimport.pxd 1970-01-01 01:00:00.000000000 +0100 +++ new/Cython-0.29.16/tests/compile/ctuple_cimport.pxd 2020-03-24 15:54:39.000000000 +0100 @@ -0,0 +1,15 @@ +# Verify defined before function prototype +cdef (int, int) get_a_ctuple() + +# Verify defined before typedef +ctypedef (int, double) int_double + +# Verify typedef defined +cdef int_double tuple_global = (1, 2.) + +# Verify defined before opt args +cdef void test_opt_args((double, int) x=*) + +# Verify defined before class declaration +cdef class CTupleClass: + cdef void get_a_ctuple(self, (double, double) x) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/compile/ctuple_cimport_T1427.pyx new/Cython-0.29.16/tests/compile/ctuple_cimport_T1427.pyx --- old/Cython-0.29.15/tests/compile/ctuple_cimport_T1427.pyx 1970-01-01 01:00:00.000000000 +0100 +++ new/Cython-0.29.16/tests/compile/ctuple_cimport_T1427.pyx 2020-03-24 15:54:39.000000000 +0100 @@ -0,0 +1,9 @@ +# ticket: 1427 +# mode: compile + +cimport ctuple_cimport + +# Verify same tuple defined in multiple pxd not redeclared +ctypedef (int, double) int_double + +ctuple_cimport.get_a_ctuple() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/run/cpp_operator_exc_handling.pyx new/Cython-0.29.16/tests/run/cpp_operator_exc_handling.pyx --- old/Cython-0.29.15/tests/run/cpp_operator_exc_handling.pyx 2016-12-10 16:41:15.000000000 +0100 +++ new/Cython-0.29.16/tests/run/cpp_operator_exc_handling.pyx 2020-03-24 15:54:39.000000000 +0100 @@ -42,6 +42,10 @@ wrapped_int &operator=(const wrapped_int &other) except +ArithmeticError wrapped_int &operator=(const long long &vao) except + + cdef cppclass second_call_is_different: + second_call_is_different() + bool operator<(const second_call_is_different&) except + + def assert_raised(f, *args, **kwargs): err = kwargs.get('err', None) @@ -268,3 +272,13 @@ assert_raised(separate_exceptions, 4, 1, 1, 1, 3, err=ArithmeticError) assert_raised(call_temp_separation, 2, 1, 4, err=AttributeError) assert_raised(call_temp_separation, 2, 4, 1, err=IndexError) + +def test_only_single_call(): + """ + Previous version of the operator handling code called the operator twice + (Resulting in a crash) + >>> test_only_single_call() + False + """ + cdef second_call_is_different inst + return inst<inst diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/run/cpp_operator_exc_handling_helper.hpp new/Cython-0.29.16/tests/run/cpp_operator_exc_handling_helper.hpp --- old/Cython-0.29.15/tests/run/cpp_operator_exc_handling_helper.hpp 2016-12-10 16:41:15.000000000 +0100 +++ new/Cython-0.29.16/tests/run/cpp_operator_exc_handling_helper.hpp 2020-03-24 15:54:39.000000000 +0100 @@ -201,3 +201,16 @@ return *this; } }; + +class second_call_is_different { + int count; + public: + second_call_is_different(): count(0) {} + bool operator<(const second_call_is_different& lhs) { + if (count>0) { + return true; + } + ++count; + return false; + } +}; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/run/cython_includes.pyx new/Cython-0.29.16/tests/run/cython_includes.pyx --- old/Cython-0.29.15/tests/run/cython_includes.pyx 2019-11-01 15:13:39.000000000 +0100 +++ new/Cython-0.29.16/tests/run/cython_includes.pyx 2020-03-24 15:54:39.000000000 +0100 @@ -18,10 +18,12 @@ cimport cpython.exc cimport cpython.float cimport cpython.function +cimport cpython.genobject cimport cpython.getargs cimport cpython.instance cimport cpython.int cimport cpython.iterator +cimport cpython.iterobject cimport cpython.list cimport cpython.long cimport cpython.longintrepr diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/run/fused_def.pyx new/Cython-0.29.16/tests/run/fused_def.pyx --- old/Cython-0.29.15/tests/run/fused_def.pyx 2019-02-27 13:23:19.000000000 +0100 +++ new/Cython-0.29.16/tests/run/fused_def.pyx 2020-03-24 15:54:39.000000000 +0100 @@ -7,6 +7,9 @@ cy = __import__("cython") cimport cython +cdef extern from *: + int __Pyx_CyFunction_Check(object) + cdef class Base(object): def __repr__(self): return type(self).__name__ @@ -128,6 +131,16 @@ print cython.typeof(obj), cython.typeof(myf), cython.typeof(myi) print obj, "%.2f" % myf, myi, "%.2f" % f, i +def run_cyfunction_check(): + """ + tp_base of the fused function was being set incorrectly meaning + it wasn't being identified as a CyFunction + >>> run_cyfunction_check() + fused_cython_function + 1 + """ + print(type(opt_func).__name__) + print(__Pyx_CyFunction_Check(opt_func)) # should be True def test_opt_func(): """ @@ -405,3 +418,31 @@ >>> test_decorators.order [3, 2, 1] """ + [email protected](True) +def bind_me(self, cython.floating a=1.): + return a + +cdef class HasBound: + """ + Using default arguments of bound specialized fused functions used to cause a segfault + https://github.com/cython/cython/issues/3370 + >>> inst = HasBound() + >>> inst.func() + 1.0 + >>> inst.func(2) + 2.0 + >>> inst.func_fused() + 1.0 + >>> inst.func_fused(2.) + 2.0 + >>> bind_me.__defaults__ + (1.0,) + >>> inst.func.__defaults__ + (1.0,) + >>> inst.func_fused.__defaults__ + (1.0,) + """ + func = bind_me[float] + + func_fused = bind_me diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/run/if_else_expr.pyx new/Cython-0.29.16/tests/run/if_else_expr.pyx --- old/Cython-0.29.15/tests/run/if_else_expr.pyx 2016-12-10 16:41:15.000000000 +0100 +++ new/Cython-0.29.16/tests/run/if_else_expr.pyx 2020-03-24 15:54:39.000000000 +0100 @@ -55,3 +55,15 @@ y = 0 if 1.0else 1 z = 0 if 1.else 1 return x, y, z + + +from libc cimport math + +def test_cfunc_ptrs(double x, bint round_down): + """ + >>> test_cfunc_ptrs(2.5, round_down=True) + 2.0 + >>> test_cfunc_ptrs(2.5, round_down=False) + 3.0 + """ + return (math.floor if round_down else math.ceil)(x) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/run/sequential_parallel.pyx new/Cython-0.29.16/tests/run/sequential_parallel.pyx --- old/Cython-0.29.15/tests/run/sequential_parallel.pyx 2019-02-08 20:14:39.000000000 +0100 +++ new/Cython-0.29.16/tests/run/sequential_parallel.pyx 2020-03-24 15:54:39.000000000 +0100 @@ -378,11 +378,7 @@ def test_nested_break_continue(): """ - DISABLED. For some reason this fails intermittently on jenkins, with - the first line of output being '0 0 0 0'. The generated code looks - awfully correct though... needs investigation - - >> test_nested_break_continue() + >>> test_nested_break_continue() 6 7 6 7 8 """ @@ -770,3 +766,53 @@ with gil: l[0] += i return l[0] + + +cdef extern from *: + """ + #ifdef _OPENMP + #define _get_addr(_x, _idx) &_x + #else + #define _get_addr(_x, _idx) (&_x+_idx) + #endif + #define address_of_temp(store, temp, idx) store = _get_addr(temp, idx) + #define address_of_temp2(store, ignore, temp, idx) store = _get_addr(temp, idx) + + double get_value() { + return 1.0; + } + """ + void address_of_temp(...) nogil + void address_of_temp2(...) nogil + double get_value() nogil except -1.0 # will generate a temp for exception checking + +def test_inner_private(): + """ + Determines if a temp variable is private by taking its address in multiple threads + and seeing if they're the same (thread private variables should have different + addresses + >>> test_inner_private() + ok + """ + cdef double* not_parallel[2] + cdef double* inner_vals[2] + cdef double* outer_vals[2] + cdef Py_ssize_t n, m + + for n in range(2): + address_of_temp(not_parallel[n], get_value(), 0) + assert not_parallel[0] == not_parallel[1], "Addresses should be the same since they come from the same temp" + + for n in prange(2, num_threads=2, schedule='static', chunksize=1, nogil=True): + address_of_temp(outer_vals[n], get_value(), n) + for m in prange(1): + # second temp just ensures different numbering + address_of_temp2(inner_vals[n], get_value(), get_value(), n) + + inner_are_the_same = inner_vals[0] == inner_vals[1] + outer_are_the_same = outer_vals[0] == outer_vals[1] + + assert outer_are_the_same == False, "Temporary variables in outer loop should be private" + assert inner_are_the_same == False, "Temporary variables in inner loop should be private" + + print('ok') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/Cython-0.29.15/tests/run/test_unicode_string_tests.pxi new/Cython-0.29.16/tests/run/test_unicode_string_tests.pxi --- old/Cython-0.29.15/tests/run/test_unicode_string_tests.pxi 2019-05-27 21:37:21.000000000 +0200 +++ new/Cython-0.29.16/tests/run/test_unicode_string_tests.pxi 2020-03-24 15:54:39.000000000 +0100 @@ -993,6 +993,14 @@ self.checkequal('\u019b\u1d00\u1d86\u0221\u1fb7', '\u019b\u1d00\u1d86\u0221\u1fb7', 'capitalize') + def test_list_concat(self): + # https://github.com/cython/cython/issues/3426 + y = [] + y += 'ab' + self.assertEqual('a', y[0]) + self.assertEqual('b', y[1]) + self.assertEqual(['a', 'b'], y) + class MixinStrUnicodeUserStringTest: # additional tests that only work for
