Hello community,

here is the log from the commit of package python-Cython for openSUSE:Factory 
checked in at 2020-06-21 18:49:14
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-Cython (Old)
 and      /work/SRC/openSUSE:Factory/.python-Cython.new.3606 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-Cython"

Sun Jun 21 18:49:14 2020 rev:56 rq:813397 version:0.29.20

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-Cython/python-Cython.changes      
2020-05-28 09:09:02.247982443 +0200
+++ /work/SRC/openSUSE:Factory/.python-Cython.new.3606/python-Cython.changes    
2020-06-21 19:02:41.928278581 +0200
@@ -1,0 +2,19 @@
+Thu Jun 11 06:30:55 UTC 2020 - Paolo Stivanin <i...@paolostivanin.com>
+
+- Update to 0.29.20
+  * Nested try-except statements with multiple return statements
+    could crash due to incorrect deletion of the except as target variable.
+  * The @classmethod decorator no longer rejects unknown input from other 
decorators.
+  * Fused types could leak into unrelated usages. Patch by David Woods.
+  * Now uses Py_SET_SIZE() and Py_SET_REFCNT() in Py3.9+ to avoid
+    low-level write access to these object field
+  * The built-in abs() function could lead to undefined behaviour when used on
+    the negative-most value of a signed C integer type
+  * Usages of sizeof() and typeid() on uninitialised variables no longer 
produce a warning
+  * The C++ typeid() function was allowed in C mode
+  * The error position reported for errors found in f-strings was misleading
+  * The new c_api_binop_methods directive was added for forward compatibility,
+    but can only be set to True (the current default value). It can be 
disabled in Cython 3.0
+
+
+-------------------------------------------------------------------

Old:
----
  Cython-0.29.19.tar.gz

New:
----
  Cython-0.29.20.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-Cython.spec ++++++
--- /var/tmp/diff_new_pack.IJGxQP/_old  2020-06-21 19:02:42.348280000 +0200
+++ /var/tmp/diff_new_pack.IJGxQP/_new  2020-06-21 19:02:42.352280013 +0200
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 %define         oldpython python
 Name:           python-Cython
-Version:        0.29.19
+Version:        0.29.20
 Release:        0
 Summary:        The Cython compiler for writing C extensions for the Python 
language
 License:        Apache-2.0

++++++ Cython-0.29.19.tar.gz -> Cython-0.29.20.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/.gitrev new/Cython-0.29.20/.gitrev
--- old/Cython-0.29.19/.gitrev  2020-05-20 21:19:28.000000000 +0200
+++ new/Cython-0.29.20/.gitrev  2020-06-10 15:13:39.000000000 +0200
@@ -1 +1 @@
-2c3a8c12b7c51f287a2a1475fb7d06eadde83baf
+9bc3fc65e906c7b1f5e4e19c92cb726b0ef361bb
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/CHANGES.rst 
new/Cython-0.29.20/CHANGES.rst
--- old/Cython-0.29.19/CHANGES.rst      2020-05-20 21:19:13.000000000 +0200
+++ new/Cython-0.29.20/CHANGES.rst      2020-06-10 15:13:18.000000000 +0200
@@ -2,6 +2,44 @@
 Cython Changelog
 ================
 
+0.29.20 (2020-06-10)
+====================
+
+Bugs fixed
+----------
+
+* Nested try-except statements with multiple ``return`` statements could crash
+  due to incorrect deletion of the ``except as`` target variable.
+  (Github issue #3666)
+
+* The ``@classmethod`` decorator no longer rejects unknown input from other 
decorators.
+  Patch by David Woods.  (Github issue #3660)
+
+* Fused types could leak into unrelated usages.
+  Patch by David Woods.  (Github issue #3642)
+
+* Now uses ``Py_SET_SIZE()`` and ``Py_SET_REFCNT()`` in Py3.9+ to avoid 
low-level
+  write access to these object fields.
+  Patch by Victor Stinner.  (Github issue #3639)
+
+* The built-in ``abs()`` function could lead to undefined behaviour when used 
on
+  the negative-most value of a signed C integer type.
+  Patch by Serge Guelton.  (Github issue #1911)
+
+* Usages of ``sizeof()`` and ``typeid()`` on uninitialised variables no longer
+  produce a warning.
+  Patch by Celelibi.  (Github issue #3575)
+
+* The C++ ``typeid()`` function was allowed in C mode.
+  Patch by Celelibi.  (Github issue #3637)
+
+* The error position reported for errors found in f-strings was misleading.
+  (Github issue #3674)
+
+* The new ``c_api_binop_methods`` directive was added for forward 
compatibility, but can
+  only be set to True (the current default value).  It can be disabled in 
Cython 3.0.
+
+
 0.29.19 (2020-05-20)
 ====================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/Code.py 
new/Cython-0.29.20/Cython/Compiler/Code.py
--- old/Cython-0.29.19/Cython/Compiler/Code.py  2020-05-19 10:45:14.000000000 
+0200
+++ new/Cython-0.29.20/Cython/Compiler/Code.py  2020-06-10 15:13:18.000000000 
+0200
@@ -543,7 +543,7 @@
 
         impl = re.sub(r'PY(IDENT|UNICODE)\("([^"]+)"\)', externalise, impl)
         assert 'PYIDENT(' not in impl and 'PYUNICODE(' not in impl
-        return bool(replacements), impl
+        return True, impl
 
     def inject_unbound_methods(self, impl, output):
         """Replace 'UNBOUND_METHOD(type, "name")' by a constant Python 
identifier cname.
@@ -551,7 +551,6 @@
         if 'CALL_UNBOUND_METHOD(' not in impl:
             return False, impl
 
-        utility_code = set()
         def externalise(matchobj):
             type_cname, method_name, obj_cname, args = matchobj.groups()
             args = [arg.strip() for arg in args[1:].split(',')] if args else []
@@ -567,9 +566,7 @@
             r'\)', externalise, impl)
         assert 'CALL_UNBOUND_METHOD(' not in impl
 
-        for helper in sorted(utility_code):
-            output.use_utility_code(UtilityCode.load_cached(helper, 
"ObjectHandling.c"))
-        return bool(utility_code), impl
+        return True, impl
 
     def wrap_c_strings(self, impl):
         """Replace CSTRING('''xyz''') by a C compatible string
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/ExprNodes.py 
new/Cython-0.29.20/Cython/Compiler/ExprNodes.py
--- old/Cython-0.29.19/Cython/Compiler/ExprNodes.py     2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Compiler/ExprNodes.py     2020-06-10 
15:13:18.000000000 +0200
@@ -5471,7 +5471,7 @@
         func_type = self.function_type()
         if func_type.is_pyobject:
             self.gil_error()
-        elif not getattr(func_type, 'nogil', False):
+        elif not func_type.is_error and not getattr(func_type, 'nogil', False):
             self.gil_error()
 
     gil_message = "Calling gil-requiring function"
@@ -5839,6 +5839,17 @@
         if function.is_name or function.is_attribute:
             code.globalstate.use_entry_utility_code(function.entry)
 
+        abs_function_cnames = ('abs', 'labs', '__Pyx_abs_longlong')
+        is_signed_int = self.type.is_int and self.type.signed
+        if self.overflowcheck and is_signed_int and function.result() in 
abs_function_cnames:
+            
code.globalstate.use_utility_code(UtilityCode.load_cached("Common", 
"Overflow.c"))
+            code.putln('if (unlikely(%s == __PYX_MIN(%s))) {\
+                PyErr_SetString(PyExc_OverflowError,\
+                                "Trying to take the absolute value of the most 
negative integer is not defined."); %s; }' % (
+                            self.args[0].result(),
+                            self.args[0].type.empty_declaration_code(),
+                            code.error_goto(self.pos)))
+
         if not function.type.is_pyobject or len(self.arg_tuple.args) > 1 or (
                 self.arg_tuple.args and self.arg_tuple.is_literal):
             super(SimpleCallNode, self).generate_evaluation_code(code)
@@ -5941,13 +5952,7 @@
                                             self.result() if 
self.type.is_pyobject else None,
                                             func_type.exception_value, 
self.nogil)
                 else:
-                    if (self.overflowcheck
-                        and self.type.is_int
-                        and self.type.signed
-                        and self.function.result() in ('abs', 'labs', 
'__Pyx_abs_longlong')):
-                        goto_error = 'if (unlikely(%s < 0)) { 
PyErr_SetString(PyExc_OverflowError, "value too large"); %s; }' % (
-                            self.result(), code.error_goto(self.pos))
-                    elif exc_checks:
+                    if exc_checks:
                         goto_error = code.error_goto_if(" && 
".join(exc_checks), self.pos)
                     else:
                         goto_error = ""
@@ -10866,7 +10871,10 @@
         typeinfo_entry = typeinfo_module.lookup('type_info')
         return 
PyrexTypes.CFakeReferenceType(PyrexTypes.c_const_type(typeinfo_entry.type))
 
+    cpp_message = 'typeid operator'
+
     def analyse_types(self, env):
+        self.cpp_check(env)
         type_info = self.get_type_info_type(env)
         if not type_info:
             self.error("The 'libcpp.typeinfo' module must be cimported to use 
the typeid() operator")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/FlowControl.py 
new/Cython-0.29.20/Cython/Compiler/FlowControl.py
--- old/Cython-0.29.19/Cython/Compiler/FlowControl.py   2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Compiler/FlowControl.py   2020-06-10 
15:13:18.000000000 +0200
@@ -884,6 +884,12 @@
         self.mark_position(node)
         return node
 
+    def visit_SizeofVarNode(self, node):
+        return node
+
+    def visit_TypeidNode(self, node):
+        return node
+
     def visit_IfStatNode(self, node):
         next_block = self.flow.newblock()
         parent = self.flow.block
@@ -1192,8 +1198,6 @@
         if self.flow.loops:
             self.flow.loops[-1].exceptions.append(descr)
         self.flow.block = body_block
-        ## XXX: Is it still required
-        body_block.add_child(entry_point)
         self.flow.nextblock()
         self._visit(node.body)
         self.flow.exceptions.pop()
@@ -1227,11 +1231,18 @@
         self.mark_position(node)
         self.visitchildren(node)
 
-        for exception in self.flow.exceptions[::-1]:
-            if exception.finally_enter:
-                self.flow.block.add_child(exception.finally_enter)
-                if exception.finally_exit:
-                    exception.finally_exit.add_child(self.flow.exit_point)
+        outer_exception_handlers = iter(self.flow.exceptions[::-1])
+        for handler in outer_exception_handlers:
+            if handler.finally_enter:
+                self.flow.block.add_child(handler.finally_enter)
+                if handler.finally_exit:
+                    # 'return' goes to function exit, or to the next outer 
'finally' clause
+                    exit_point = self.flow.exit_point
+                    for next_handler in outer_exception_handlers:
+                        if next_handler.finally_enter:
+                            exit_point = next_handler.finally_enter
+                            break
+                    handler.finally_exit.add_child(exit_point)
                 break
         else:
             if self.flow.block:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/ModuleNode.py 
new/Cython-0.29.20/Cython/Compiler/ModuleNode.py
--- old/Cython-0.29.19/Cython/Compiler/ModuleNode.py    2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Compiler/ModuleNode.py    2020-06-10 
15:13:18.000000000 +0200
@@ -29,7 +29,7 @@
 from .Errors import error, warning
 from .PyrexTypes import py_object_type
 from ..Utils import open_new_file, replace_suffix, decode_filename, 
build_hex_version
-from .Code import UtilityCode, IncludeCode
+from .Code import UtilityCode, IncludeCode, TempitaUtilityCode
 from .StringEncoding import EncodedString
 from .Pythran import has_np_pythran
 
@@ -1255,6 +1255,9 @@
                         self.generate_dict_getter_function(scope, code)
                     if 
scope.defines_any_special(TypeSlots.richcmp_special_methods):
                         self.generate_richcmp_function(scope, code)
+                    for slot in TypeSlots.PyNumberMethods:
+                        if slot.is_binop and 
scope.defines_any_special(slot.user_methods):
+                            self.generate_binop_function(scope, slot, code)
                     self.generate_property_accessors(scope, code)
                     self.generate_method_table(scope, code)
                     self.generate_getset_table(scope, code)
@@ -1554,9 +1557,11 @@
         code.putln("{")
         code.putln("PyObject *etype, *eval, *etb;")
         code.putln("PyErr_Fetch(&etype, &eval, &etb);")
-        code.putln("++Py_REFCNT(o);")
+        # increase the refcount while we are calling into user code
+        # to prevent recursive deallocation
+        code.putln("__Pyx_SET_REFCNT(o, Py_REFCNT(o) + 1);")
         code.putln("%s(o);" % entry.func_cname)
-        code.putln("--Py_REFCNT(o);")
+        code.putln("__Pyx_SET_REFCNT(o, Py_REFCNT(o) - 1);")
         code.putln("PyErr_Restore(etype, eval, etb);")
         code.putln("}")
 
@@ -1892,6 +1897,64 @@
         code.putln("}")  # switch
         code.putln("}")
 
+    def generate_binop_function(self, scope, slot, code):
+        func_name = scope.mangle_internal(slot.slot_name)
+        if scope.directives['c_api_binop_methods']:
+            code.putln('#define %s %s' % (func_name, 
slot.left_slot.slot_code(scope)))
+            return
+        else:
+            error(self.pos,
+                  "The 'c_api_binop_methods' directive is only supported for 
forward compatibility"
+                  " and must be True.")
+
+        code.putln()
+        preprocessor_guard = slot.preprocessor_guard_code()
+        if preprocessor_guard:
+            code.putln(preprocessor_guard)
+
+        if slot.left_slot.signature == TypeSlots.binaryfunc:
+            slot_type = 'binaryfunc'
+            extra_arg = extra_arg_decl = ''
+        elif slot.left_slot.signature == TypeSlots.ternaryfunc:
+            slot_type = 'ternaryfunc'
+            extra_arg = ', extra_arg'
+            extra_arg_decl = ', PyObject* extra_arg'
+        else:
+            error(entry.pos, "Unexpected type lost signature: %s" % slot)
+
+        def has_slot_method(method_name):
+            entry = scope.lookup(method_name)
+            return bool(entry and entry.is_special and entry.func_cname)
+        def call_slot_method(method_name, reverse):
+            entry = scope.lookup(method_name)
+            if entry and entry.is_special and entry.func_cname:
+                return "%s(%s%s)" % (
+                    entry.func_cname,
+                    "right, left" if reverse else "left, right",
+                    extra_arg)
+            else:
+                return '%s_maybe_call_slot(%s, left, right %s)' % (
+                    func_name,
+                    'Py_TYPE(right)->tp_base' if reverse else 
'Py_TYPE(left)->tp_base',
+                    extra_arg)
+
+        code.putln(
+            TempitaUtilityCode.load_as_string(
+                "BinopSlot", "ExtensionTypes.c",
+                context={
+                    "func_name": func_name,
+                    "slot_name": slot.slot_name,
+                    "overloads_left": 
int(has_slot_method(slot.left_slot.method_name)),
+                    "call_left": call_slot_method(slot.left_slot.method_name, 
reverse=False),
+                    "call_right": 
call_slot_method(slot.right_slot.method_name, reverse=True),
+                    "type_cname": scope.parent_type.typeptr_cname,
+                    "slot_type": slot_type,
+                    "extra_arg": extra_arg,
+                    "extra_arg_decl": extra_arg_decl,
+                    })[1])
+        if preprocessor_guard:
+            code.putln("#endif")
+
     def generate_getattro_function(self, scope, code):
         # First try to get the attribute using __getattribute__, if defined, or
         # PyObject_GenericGetAttr.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/Nodes.py 
new/Cython-0.29.20/Cython/Compiler/Nodes.py
--- old/Cython-0.29.19/Cython/Compiler/Nodes.py 2020-05-19 10:45:14.000000000 
+0200
+++ new/Cython-0.29.20/Cython/Compiler/Nodes.py 2020-06-10 15:13:18.000000000 
+0200
@@ -1023,8 +1023,6 @@
                 if scope is None:
                     # Maybe it's a cimport.
                     scope = env.find_imported_module(self.module_path, 
self.pos)
-                    if scope:
-                        scope.fused_to_specific = env.fused_to_specific
             else:
                 scope = env
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/Options.py 
new/Cython-0.29.20/Cython/Compiler/Options.py
--- old/Cython-0.29.19/Cython/Compiler/Options.py       2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Compiler/Options.py       2020-06-10 
15:13:18.000000000 +0200
@@ -178,6 +178,7 @@
     'auto_pickle': None,
     'cdivision': False,  # was True before 0.12
     'cdivision_warnings': False,
+    'c_api_binop_methods': True,  # Change for 3.0
     'overflowcheck': False,
     'overflowcheck.fold': True,
     'always_allow_keywords': False,
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/Parsing.pxd 
new/Cython-0.29.20/Cython/Compiler/Parsing.pxd
--- old/Cython-0.29.19/Cython/Compiler/Parsing.pxd      2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Compiler/Parsing.pxd      2020-06-10 
15:13:18.000000000 +0200
@@ -69,7 +69,8 @@
 @cython.locals(systr=unicode, is_python3_source=bint, is_raw=bint)
 cdef p_string_literal(PyrexScanner s, kind_override=*)
 cdef _append_escape_sequence(kind, builder, unicode escape_sequence, 
PyrexScanner s)
-@cython.locals(i=Py_ssize_t, size=Py_ssize_t, c=Py_UCS4)
+cdef tuple _f_string_error_pos(pos, string, Py_ssize_t i)
+@cython.locals(i=Py_ssize_t, size=Py_ssize_t, c=Py_UCS4, next_start=Py_ssize_t)
 cdef list p_f_string(PyrexScanner s, unicode_value, pos, bint is_raw)
 @cython.locals(i=Py_ssize_t, size=Py_ssize_t, c=Py_UCS4, quote_char=Py_UCS4, 
NO_CHAR=Py_UCS4)
 cdef tuple p_f_string_expr(PyrexScanner s, unicode_value, pos, Py_ssize_t 
starting_index, bint is_raw)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/Parsing.py 
new/Cython-0.29.20/Cython/Compiler/Parsing.py
--- old/Cython-0.29.19/Cython/Compiler/Parsing.py       2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Compiler/Parsing.py       2020-06-10 
15:13:18.000000000 +0200
@@ -882,6 +882,7 @@
     pos = s.position()
     is_python3_source = s.context.language_level >= 3
     has_non_ascii_literal_characters = False
+    string_start_pos = (pos[0], pos[1], pos[2] + len(s.systring))
     kind_string = s.systring.rstrip('"\'').lower()
     if len(kind_string) > 1:
         if len(set(kind_string)) != len(kind_string):
@@ -965,7 +966,7 @@
                 s.error("bytes can only contain ASCII literal characters.", 
pos=pos)
             bytes_value = None
     if kind == 'f':
-        unicode_value = p_f_string(s, unicode_value, pos, is_raw='r' in 
kind_string)
+        unicode_value = p_f_string(s, unicode_value, string_start_pos, 
is_raw='r' in kind_string)
     s.next()
     return (kind, bytes_value, unicode_value)
 
@@ -1037,6 +1038,10 @@
     for is_raw in (True, False)]
 
 
+def _f_string_error_pos(pos, string, i):
+    return (pos[0], pos[1], pos[2] + i + 1)  # FIXME: handle newlines in string
+
+
 def p_f_string(s, unicode_value, pos, is_raw):
     # Parses a PEP 498 f-string literal into a list of nodes. Nodes are either 
UnicodeNodes
     # or FormattedValueNodes.
@@ -1044,15 +1049,13 @@
     next_start = 0
     size = len(unicode_value)
     builder = StringEncoding.UnicodeLiteralBuilder()
-    error_pos = list(pos)  # [src, line, column]
     _parse_seq = _parse_escape_sequences_raw if is_raw else 
_parse_escape_sequences
 
     while next_start < size:
         end = next_start
-        error_pos[2] = pos[2] + end  # FIXME: handle newlines in string
         match = _parse_seq(unicode_value, next_start)
         if match is None:
-            error(tuple(error_pos), "Invalid escape sequence")
+            error(_f_string_error_pos(pos, unicode_value, next_start), 
"Invalid escape sequence")
 
         next_start = match.end()
         part = match.group()
@@ -1076,7 +1079,8 @@
             if part == '}}':
                 builder.append('}')
             else:
-                s.error("f-string: single '}' is not allowed", 
pos=tuple(error_pos))
+                error(_f_string_error_pos(pos, unicode_value, end),
+                      "f-string: single '}' is not allowed")
         else:
             builder.append(part)
 
@@ -1097,16 +1101,20 @@
     nested_depth = 0
     quote_char = NO_CHAR
     in_triple_quotes = False
+    backslash_reported = False
 
     while True:
         if i >= size:
-            s.error("missing '}' in format string expression")
+            break  # error will be reported below
         c = unicode_value[i]
 
         if quote_char != NO_CHAR:
             if c == '\\':
-                error_pos = (pos[0], pos[1] + i, pos[2])  # FIXME: handle 
newlines in string
-                error(error_pos, "backslashes not allowed in f-strings")
+                # avoid redundant error reports along '\' sequences
+                if not backslash_reported:
+                    error(_f_string_error_pos(pos, unicode_value, i),
+                          "backslashes not allowed in f-strings")
+                backslash_reported = True
             elif c == quote_char:
                 if in_triple_quotes:
                     if i + 2 < size and unicode_value[i + 1] == c and 
unicode_value[i + 2] == c:
@@ -1125,7 +1133,8 @@
         elif nested_depth != 0 and c in '}])':
             nested_depth -= 1
         elif c == '#':
-            s.error("format string cannot include #")
+            error(_f_string_error_pos(pos, unicode_value, i),
+                  "format string cannot include #")
         elif nested_depth == 0 and c in '!:}':
             # allow != as a special case
             if c == '!' and i + 1 < size and unicode_value[i + 1] == '=':
@@ -1141,12 +1150,13 @@
     expr_pos = (pos[0], pos[1], pos[2] + starting_index + 2)  # TODO: find 
exact code position (concat, multi-line, ...)
 
     if not expr_str.strip():
-        error(expr_pos, "empty expression not allowed in f-string")
+        error(_f_string_error_pos(pos, unicode_value, starting_index),
+              "empty expression not allowed in f-string")
 
     if terminal_char == '!':
         i += 1
         if i + 2 > size:
-            error(expr_pos, "invalid conversion char at end of string")
+            pass  # error will be reported below
         else:
             conversion_char = unicode_value[i]
             i += 1
@@ -1159,7 +1169,7 @@
         start_format_spec = i + 1
         while True:
             if i >= size:
-                s.error("missing '}' in format specifier", pos=expr_pos)
+                break  # error will be reported below
             c = unicode_value[i]
             if not in_triple_quotes and not in_string:
                 if c == '{':
@@ -1181,7 +1191,9 @@
         format_spec_str = unicode_value[start_format_spec:i]
 
     if terminal_char != '}':
-        s.error("missing '}' in format string expression', found '%s'" % 
terminal_char)
+        error(_f_string_error_pos(pos, unicode_value, i),
+              "missing '}' in format string expression" + (
+                  ", found '%s'" % terminal_char if terminal_char else ""))
 
     # parse the expression as if it was surrounded by parentheses
     buf = StringIO('(%s)' % expr_str)
@@ -1190,7 +1202,7 @@
 
     # validate the conversion char
     if conversion_char is not None and not 
ExprNodes.FormattedValueNode.find_conversion_func(conversion_char):
-        error(pos, "invalid conversion character '%s'" % conversion_char)
+        error(expr_pos, "invalid conversion character '%s'" % conversion_char)
 
     # the format spec is itself treated like an f-string
     if format_spec_str:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Compiler/TypeSlots.py 
new/Cython-0.29.20/Cython/Compiler/TypeSlots.py
--- old/Cython-0.29.19/Cython/Compiler/TypeSlots.py     2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Compiler/TypeSlots.py     2020-06-10 
15:13:18.000000000 +0200
@@ -180,13 +180,14 @@
     #  ifdef                         Full #ifdef string that slot is wrapped 
in. Using this causes py3, py2 and flags to be ignored.)
 
     def __init__(self, slot_name, dynamic=False, inherited=False,
-                 py3=True, py2=True, ifdef=None):
+                 py3=True, py2=True, ifdef=None, is_binop=False):
         self.slot_name = slot_name
         self.is_initialised_dynamically = dynamic
         self.is_inherited = inherited
         self.ifdef = ifdef
         self.py3 = py3
         self.py2 = py2
+        self.is_binop = is_binop
 
     def preprocessor_guard_code(self):
         ifdef = self.ifdef
@@ -405,6 +406,17 @@
             return self.default_value
 
 
+class BinopSlot(SyntheticSlot):
+    def __init__(self, signature, slot_name, left_method, **kargs):
+        assert left_method.startswith('__')
+        right_method = '__r' + left_method[2:]
+        SyntheticSlot.__init__(
+                self, slot_name, [left_method, right_method], "0", 
is_binop=True, **kargs)
+        # MethodSlot causes special method registration.
+        self.left_slot = MethodSlot(signature, "", left_method)
+        self.right_slot = MethodSlot(signature, "", right_method)
+
+
 class RichcmpSlot(MethodSlot):
     def slot_code(self, scope):
         entry = scope.lookup_here(self.method_name)
@@ -728,23 +740,23 @@
 PyNumberMethods_Py3_GUARD = "PY_MAJOR_VERSION < 3 || (CYTHON_COMPILING_IN_PYPY 
&& PY_VERSION_HEX < 0x03050000)"
 
 PyNumberMethods = (
-    MethodSlot(binaryfunc, "nb_add", "__add__"),
-    MethodSlot(binaryfunc, "nb_subtract", "__sub__"),
-    MethodSlot(binaryfunc, "nb_multiply", "__mul__"),
-    MethodSlot(binaryfunc, "nb_divide", "__div__", ifdef = 
PyNumberMethods_Py3_GUARD),
-    MethodSlot(binaryfunc, "nb_remainder", "__mod__"),
-    MethodSlot(binaryfunc, "nb_divmod", "__divmod__"),
-    MethodSlot(ternaryfunc, "nb_power", "__pow__"),
+    BinopSlot(binaryfunc, "nb_add", "__add__"),
+    BinopSlot(binaryfunc, "nb_subtract", "__sub__"),
+    BinopSlot(binaryfunc, "nb_multiply", "__mul__"),
+    BinopSlot(binaryfunc, "nb_divide", "__div__", ifdef = 
PyNumberMethods_Py3_GUARD),
+    BinopSlot(binaryfunc, "nb_remainder", "__mod__"),
+    BinopSlot(binaryfunc, "nb_divmod", "__divmod__"),
+    BinopSlot(ternaryfunc, "nb_power", "__pow__"),
     MethodSlot(unaryfunc, "nb_negative", "__neg__"),
     MethodSlot(unaryfunc, "nb_positive", "__pos__"),
     MethodSlot(unaryfunc, "nb_absolute", "__abs__"),
     MethodSlot(inquiry, "nb_nonzero", "__nonzero__", py3 = ("nb_bool", 
"__bool__")),
     MethodSlot(unaryfunc, "nb_invert", "__invert__"),
-    MethodSlot(binaryfunc, "nb_lshift", "__lshift__"),
-    MethodSlot(binaryfunc, "nb_rshift", "__rshift__"),
-    MethodSlot(binaryfunc, "nb_and", "__and__"),
-    MethodSlot(binaryfunc, "nb_xor", "__xor__"),
-    MethodSlot(binaryfunc, "nb_or", "__or__"),
+    BinopSlot(binaryfunc, "nb_lshift", "__lshift__"),
+    BinopSlot(binaryfunc, "nb_rshift", "__rshift__"),
+    BinopSlot(binaryfunc, "nb_and", "__and__"),
+    BinopSlot(binaryfunc, "nb_xor", "__xor__"),
+    BinopSlot(binaryfunc, "nb_or", "__or__"),
     EmptySlot("nb_coerce", ifdef = PyNumberMethods_Py3_GUARD),
     MethodSlot(unaryfunc, "nb_int", "__int__", fallback="__long__"),
     MethodSlot(unaryfunc, "nb_long", "__long__", fallback="__int__", py3 = 
"<RESERVED>"),
@@ -767,8 +779,8 @@
 
     # Added in release 2.2
     # The following require the Py_TPFLAGS_HAVE_CLASS flag
-    MethodSlot(binaryfunc, "nb_floor_divide", "__floordiv__"),
-    MethodSlot(binaryfunc, "nb_true_divide", "__truediv__"),
+    BinopSlot(binaryfunc, "nb_floor_divide", "__floordiv__"),
+    BinopSlot(binaryfunc, "nb_true_divide", "__truediv__"),
     MethodSlot(ibinaryfunc, "nb_inplace_floor_divide", "__ifloordiv__"),
     MethodSlot(ibinaryfunc, "nb_inplace_true_divide", "__itruediv__"),
 
@@ -776,7 +788,7 @@
     MethodSlot(unaryfunc, "nb_index", "__index__"),
 
     # Added in release 3.5
-    MethodSlot(binaryfunc, "nb_matrix_multiply", "__matmul__", 
ifdef="PY_VERSION_HEX >= 0x03050000"),
+    BinopSlot(binaryfunc, "nb_matrix_multiply", "__matmul__", 
ifdef="PY_VERSION_HEX >= 0x03050000"),
     MethodSlot(ibinaryfunc, "nb_inplace_matrix_multiply", "__imatmul__", 
ifdef="PY_VERSION_HEX >= 0x03050000"),
 )
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Shadow.py 
new/Cython-0.29.20/Cython/Shadow.py
--- old/Cython-0.29.19/Cython/Shadow.py 2020-05-20 21:19:13.000000000 +0200
+++ new/Cython-0.29.20/Cython/Shadow.py 2020-06-10 15:13:18.000000000 +0200
@@ -1,7 +1,7 @@
 # cython.* namespace for pure mode.
 from __future__ import absolute_import
 
-__version__ = "0.29.19"
+__version__ = "0.29.20"
 
 try:
     from __builtin__ import basestring
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Utility/Builtins.c 
new/Cython-0.29.20/Cython/Utility/Builtins.c
--- old/Cython-0.29.19/Cython/Utility/Builtins.c        2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Utility/Builtins.c        2020-06-10 
15:13:18.000000000 +0200
@@ -279,7 +279,8 @@
     {
         PyObject *copy = _PyLong_Copy((PyLongObject*)n);
         if (likely(copy)) {
-            Py_SIZE(copy) = -(Py_SIZE(copy));
+            // negate the size to swap the sign
+            __Pyx_SET_SIZE(copy, -Py_SIZE(copy));
         }
         return copy;
     }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Utility/CythonFunction.c 
new/Cython-0.29.20/Cython/Utility/CythonFunction.c
--- old/Cython-0.29.19/Cython/Utility/CythonFunction.c  2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Utility/CythonFunction.c  2020-06-10 
15:13:18.000000000 +0200
@@ -1292,7 +1292,8 @@
     // special C-API function only in Pyston and PyPy >= 5.9
     if (PyMethodDescr_Check(method))
 #else
-    // It appears that PyMethodDescr_Type is not exposed anywhere in the 
CPython C-API
+    #if PY_MAJOR_VERSION == 2
+    // PyMethodDescr_Type is not exposed in the CPython C-API in Py2.
     static PyTypeObject *methoddescr_type = NULL;
     if (methoddescr_type == NULL) {
        PyObject *meth = PyObject_GetAttrString((PyObject*)&PyList_Type, 
"append");
@@ -1300,6 +1301,9 @@
        methoddescr_type = Py_TYPE(meth);
        Py_DECREF(meth);
     }
+    #else
+    PyTypeObject *methoddescr_type = &PyMethodDescr_Type;
+    #endif
     if (__Pyx_TypeCheck(method, methoddescr_type))
 #endif
     {
@@ -1317,16 +1321,7 @@
         // python classes
         return PyClassMethod_New(PyMethod_GET_FUNCTION(method));
     }
-    else if (PyCFunction_Check(method)) {
+    else {
         return PyClassMethod_New(method);
     }
-#ifdef __Pyx_CyFunction_USED
-    else if (__Pyx_CyFunction_Check(method)) {
-        return PyClassMethod_New(method);
-    }
-#endif
-    PyErr_SetString(PyExc_TypeError,
-                   "Class-level classmethod() can only be called on "
-                   "a method_descriptor or instance method.");
-    return NULL;
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Utility/ExtensionTypes.c 
new/Cython-0.29.20/Cython/Utility/ExtensionTypes.c
--- old/Cython-0.29.19/Cython/Utility/ExtensionTypes.c  2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Utility/ExtensionTypes.c  2020-06-10 
15:13:18.000000000 +0200
@@ -278,3 +278,56 @@
     Py_XDECREF(setstate_cython);
     return ret;
 }
+
+/////////////// BinopSlot ///////////////
+
+static CYTHON_INLINE PyObject *{{func_name}}_maybe_call_slot(PyTypeObject* 
type, PyObject *left, PyObject *right {{extra_arg_decl}}) {
+    {{slot_type}} slot;
+#if CYTHON_USE_TYPE_SLOTS
+    slot = type->tp_as_number ? type->tp_as_number->{{slot_name}} : NULL;
+#else
+    slot = ({{slot_type}}) PyType_GetSlot(type, Py_{{slot_name}});
+#endif
+    return slot ? slot(left, right {{extra_arg}}) : 
__Pyx_NewRef(Py_NotImplemented);
+}
+
+static PyObject *{{func_name}}(PyObject *left, PyObject *right 
{{extra_arg_decl}}) {
+    PyObject *res;
+    int maybe_self_is_left, maybe_self_is_right = 0;
+    maybe_self_is_left = Py_TYPE(left) == Py_TYPE(right)
+#if CYTHON_USE_TYPE_SLOTS
+            || (Py_TYPE(left)->tp_as_number && 
Py_TYPE(left)->tp_as_number->{{slot_name}} == &{{func_name}})
+#endif
+            || __Pyx_TypeCheck(left, {{type_cname}});
+    // Optimize for the common case where the left operation is defined (and 
successful).
+    if (!{{overloads_left}}) {
+        maybe_self_is_right = Py_TYPE(left) == Py_TYPE(right)
+#if CYTHON_USE_TYPE_SLOTS
+                || (Py_TYPE(right)->tp_as_number && 
Py_TYPE(right)->tp_as_number->{{slot_name}} == &{{func_name}})
+#endif
+                || __Pyx_TypeCheck(right, {{type_cname}});
+    }
+    if (maybe_self_is_left) {
+        if (maybe_self_is_right && !{{overloads_left}}) {
+            res = {{call_right}};
+            if (res != Py_NotImplemented) return res;
+            Py_DECREF(res);
+            // Don't bother calling it again.
+            maybe_self_is_right = 0;
+        }
+        res = {{call_left}};
+        if (res != Py_NotImplemented) return res;
+        Py_DECREF(res);
+    }
+    if ({{overloads_left}}) {
+        maybe_self_is_right = Py_TYPE(left) == Py_TYPE(right)
+#if CYTHON_USE_TYPE_SLOTS
+                || (Py_TYPE(right)->tp_as_number && 
Py_TYPE(right)->tp_as_number->{{slot_name}} == &{{func_name}})
+#endif
+                || PyType_IsSubtype(Py_TYPE(right), {{type_cname}});
+    }
+    if (maybe_self_is_right) {
+        return {{call_right}};
+    }
+    return __Pyx_NewRef(Py_NotImplemented);
+}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Utility/ModuleSetupCode.c 
new/Cython-0.29.20/Cython/Utility/ModuleSetupCode.c
--- old/Cython-0.29.19/Cython/Utility/ModuleSetupCode.c 2020-05-20 
21:19:13.000000000 +0200
+++ new/Cython-0.29.20/Cython/Utility/ModuleSetupCode.c 2020-06-10 
15:13:18.000000000 +0200
@@ -609,6 +609,15 @@
   #define PySet_CheckExact(obj)        (Py_TYPE(obj) == &PySet_Type)
 #endif
 
+
+#if PY_VERSION_HEX >= 0x030900A4
+  #define __Pyx_SET_REFCNT(obj, refcnt) Py_SET_REFCNT(obj, refcnt)
+  #define __Pyx_SET_SIZE(obj, size) Py_SET_SIZE(obj, size)
+#else
+  #define __Pyx_SET_REFCNT(obj, refcnt) Py_REFCNT(obj) = (refcnt)
+  #define __Pyx_SET_SIZE(obj, size) Py_SIZE(obj) = (size)
+#endif
+
 #if CYTHON_ASSUME_SAFE_MACROS
   #define __Pyx_PySequence_SIZE(seq)  Py_SIZE(seq)
 #else
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/Cython/Utility/Optimize.c 
new/Cython-0.29.20/Cython/Utility/Optimize.c
--- old/Cython-0.29.19/Cython/Utility/Optimize.c        2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/Cython/Utility/Optimize.c        2020-06-10 
15:13:18.000000000 +0200
@@ -35,7 +35,7 @@
     if (likely(L->allocated > len) & likely(len > (L->allocated >> 1))) {
         Py_INCREF(x);
         PyList_SET_ITEM(list, len, x);
-        Py_SIZE(list) = len+1;
+        __Pyx_SET_SIZE(list, len + 1);
         return 0;
     }
     return PyList_Append(list, x);
@@ -53,7 +53,7 @@
     if (likely(L->allocated > len)) {
         Py_INCREF(x);
         PyList_SET_ITEM(list, len, x);
-        Py_SIZE(list) = len+1;
+        __Pyx_SET_SIZE(list, len + 1);
         return 0;
     }
     return PyList_Append(list, x);
@@ -104,7 +104,7 @@
 static CYTHON_INLINE PyObject* __Pyx_PyList_Pop(PyObject* L) {
     /* Check that both the size is positive and no reallocation shrinking 
needs to be done. */
     if (likely(PyList_GET_SIZE(L) > (((PyListObject*)L)->allocated >> 1))) {
-        Py_SIZE(L) -= 1;
+        __Pyx_SET_SIZE(L, Py_SIZE(L) - 1);
         return PyList_GET_ITEM(L, PyList_GET_SIZE(L));
     }
     return CALL_UNBOUND_METHOD(PyList_Type, "pop", L);
@@ -167,7 +167,7 @@
         }
         if (likely(__Pyx_is_valid_index(cix, size))) {
             PyObject* v = PyList_GET_ITEM(L, cix);
-            Py_SIZE(L) -= 1;
+            __Pyx_SET_SIZE(L, Py_SIZE(L) - 1);
             size -= 1;
             memmove(&PyList_GET_ITEM(L, cix), &PyList_GET_ITEM(L, cix+1), 
(size_t)(size-cix)*sizeof(PyObject*));
             return v;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/PKG-INFO new/Cython-0.29.20/PKG-INFO
--- old/Cython-0.29.19/PKG-INFO 2020-05-20 21:19:36.000000000 +0200
+++ new/Cython-0.29.20/PKG-INFO 2020-06-10 15:13:46.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 1.2
 Name: Cython
-Version: 0.29.19
+Version: 0.29.20
 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.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/runtests.py 
new/Cython-0.29.20/runtests.py
--- old/Cython-0.29.19/runtests.py      2020-05-19 10:45:14.000000000 +0200
+++ new/Cython-0.29.20/runtests.py      2020-06-10 15:13:18.000000000 +0200
@@ -617,6 +617,7 @@
         self.cleanup_failures = options.cleanup_failures
         self.with_pyregr = with_pyregr
         self.cython_only = options.cython_only
+        self.doctest_selector = re.compile(options.only_pattern).search if 
options.only_pattern else None
         self.languages = languages
         self.test_bugs = test_bugs
         self.fork = options.fork
@@ -730,12 +731,14 @@
         else:
             languages = self.languages
 
-        if skip_c(tags) and 'c' in languages:
+        if 'c' in languages and skip_c(tags):
             languages = list(languages)
             languages.remove('c')
-        elif 'no-cpp' in tags['tag'] and 'cpp' in self.languages:
+        if 'cpp' in languages and 'no-cpp' in tags['tag']:
             languages = list(languages)
             languages.remove('cpp')
+        if not languages:
+            return []
 
         pythran_dir = self.pythran_dir
         if 'pythran' in tags['tag'] and not pythran_dir and 'cpp' in languages:
@@ -772,6 +775,7 @@
                           cleanup_sharedlibs=self.cleanup_sharedlibs,
                           cleanup_failures=self.cleanup_failures,
                           cython_only=self.cython_only,
+                          doctest_selector=self.doctest_selector,
                           fork=self.fork,
                           language_level=self.language_level,
                           warning_errors=warning_errors,
@@ -812,7 +816,7 @@
 class CythonCompileTestCase(unittest.TestCase):
     def __init__(self, test_directory, workdir, module, tags, language='c', 
preparse='id',
                  expect_errors=False, expect_warnings=False, annotate=False, 
cleanup_workdir=True,
-                 cleanup_sharedlibs=True, cleanup_failures=True, 
cython_only=False,
+                 cleanup_sharedlibs=True, cleanup_failures=True, 
cython_only=False, doctest_selector=None,
                  fork=True, language_level=2, warning_errors=False,
                  test_determinism=False,
                  common_utility_dir=None, pythran_dir=None, stats=None):
@@ -830,6 +834,7 @@
         self.cleanup_sharedlibs = cleanup_sharedlibs
         self.cleanup_failures = cleanup_failures
         self.cython_only = cython_only
+        self.doctest_selector = doctest_selector
         self.fork = fork
         self.language_level = language_level
         self.warning_errors = warning_errors
@@ -1276,6 +1281,8 @@
             else:
                 module = module_or_name
             tests = doctest.DocTestSuite(module)
+            if self.doctest_selector is not None:
+                tests._tests[:] = [test for test in tests._tests if 
self.doctest_selector(test.id())]
             with self.stats.time(self.name, self.language, 'run'):
                 tests.run(result)
         run_forked_test(result, run_test, self.shortDescription(), self.fork)
@@ -2058,6 +2065,8 @@
     parser.add_option("-T", "--ticket", dest="tickets",
                       action="append",
                       help="a bug ticket number to run the respective test in 
'tests/*'")
+    parser.add_option("-k", dest="only_pattern",
+                      help="a regex pattern for selecting doctests and test 
functions in the test modules")
     parser.add_option("-3", dest="language_level",
                       action="store_const", const=3, default=2,
                       help="set language level to Python 3 (useful for running 
the CPython regression tests)'")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/errors/e_cpp_only_features.pyx 
new/Cython-0.29.20/tests/errors/e_cpp_only_features.pyx
--- old/Cython-0.29.19/tests/errors/e_cpp_only_features.pyx     1970-01-01 
01:00:00.000000000 +0100
+++ new/Cython-0.29.20/tests/errors/e_cpp_only_features.pyx     2020-06-10 
15:13:18.000000000 +0200
@@ -0,0 +1,26 @@
+# mode: error
+# tag: no-cpp, werror
+
+from cython.operator import typeid
+
+def use_typeid():
+    cdef int i = 0
+    print typeid(i) == typeid(i)
+
+cdef cppclass A:
+    pass
+
+def use_new():
+    cdef A* x = new A()
+
+def use_del():
+    cdef A a = A()
+    cdef A *p = &a
+    del p
+
+_ERRORS = """
+8:10: typeid operator only allowed in c++
+8:23: typeid operator only allowed in c++
+14:20: Operation only allowed in c++
+19:4: Operation only allowed in c++
+"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/errors/e_fstring.pyx 
new/Cython-0.29.20/tests/errors/e_fstring.pyx
--- old/Cython-0.29.19/tests/errors/e_fstring.pyx       1970-01-01 
01:00:00.000000000 +0100
+++ new/Cython-0.29.20/tests/errors/e_fstring.pyx       2020-06-10 
15:13:18.000000000 +0200
@@ -0,0 +1,23 @@
+# mode: error
+# tag: fstring
+
+def incorrect_fstrings(x):
+    return [
+        f"{x}{'\\'}'{x+1}",
+        f"""{}""",
+        f"{}",
+        f"{x!}",
+        f"{",
+        f"{{}}}",
+    ]
+
+
+_ERRORS = """
+6:16: backslashes not allowed in f-strings
+7:14: empty expression not allowed in f-string
+8:12: empty expression not allowed in f-string
+9:14: missing '}' in format string expression, found '!'
+10:12: empty expression not allowed in f-string
+10:12: missing '}' in format string expression
+11:15: f-string: single '}' is not allowed
+"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/errors/w_uninitialized.pyx 
new/Cython-0.29.20/tests/errors/w_uninitialized.pyx
--- old/Cython-0.29.19/tests/errors/w_uninitialized.pyx 2018-09-22 
16:18:56.000000000 +0200
+++ new/Cython-0.29.20/tests/errors/w_uninitialized.pyx 2020-06-10 
15:13:18.000000000 +0200
@@ -112,6 +112,10 @@
     args = []
     kwargs = {}
 
+def uninitialized_in_sizeof():
+    cdef int i
+    print sizeof(i)
+
 _ERRORS = """
 6:10: local variable 'a' referenced before assignment
 12:11: local variable 'a' might be referenced before assignment
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/errors/w_uninitialized_cpp.pyx 
new/Cython-0.29.20/tests/errors/w_uninitialized_cpp.pyx
--- old/Cython-0.29.19/tests/errors/w_uninitialized_cpp.pyx     1970-01-01 
01:00:00.000000000 +0100
+++ new/Cython-0.29.20/tests/errors/w_uninitialized_cpp.pyx     2020-06-10 
15:13:18.000000000 +0200
@@ -0,0 +1,12 @@
+# cython: warn.maybe_uninitialized=True
+# mode: error
+# tag: cpp, werror
+
+from cython.operator import typeid
+
+def uninitialized_in_typeid():
+    cdef int i
+    print typeid(i) == typeid(i)
+
+_ERRORS = """
+"""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/run/builtin_abs.pyx 
new/Cython-0.29.20/tests/run/builtin_abs.pyx
--- old/Cython-0.29.19/tests/run/builtin_abs.pyx        2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/tests/run/builtin_abs.pyx        2020-06-10 
15:13:19.000000000 +0200
@@ -1,5 +1,6 @@
 # mode: run
 # ticket: 698
+# distutils: extra_compile_args=-fwrapv
 
 cdef extern from *:
     int INT_MAX
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/run/classmethod.pyx 
new/Cython-0.29.20/tests/run/classmethod.pyx
--- old/Cython-0.29.19/tests/run/classmethod.pyx        2016-12-10 
16:41:15.000000000 +0100
+++ new/Cython-0.29.20/tests/run/classmethod.pyx        2020-06-10 
15:13:19.000000000 +0200
@@ -9,6 +9,10 @@
 class1
 >>> class1().bview()
 class1
+>>> class1().cview()
+class1
+>>> class1().cview("XX")
+class1XX
 
 >>> class2.view()
 class2
@@ -35,6 +39,12 @@
 def f_plus(cls, a):
     return cls.a + a
 
+def second_decorator(f):
+    # note - a class, not a function (didn't pass Cython's test in 
__Pyx_Method_ClassMethod)
+    class C:
+        def __call__(self, *args):
+            return f(*args)
+    return C()
 
 class class1:
     a = 5
@@ -48,6 +58,11 @@
     def bview(cls):
         print cls.__name__
 
+    @classmethod
+    @second_decorator
+    def cview(cls, s=""):
+        print cls.__name__+s
+
 
 class class2(object):
     a = 6
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/run/cython3.pyx 
new/Cython-0.29.20/tests/run/cython3.pyx
--- old/Cython-0.29.19/tests/run/cython3.pyx    2020-05-19 10:45:14.000000000 
+0200
+++ new/Cython-0.29.20/tests/run/cython3.pyx    2020-06-10 15:13:19.000000000 
+0200
@@ -258,6 +258,32 @@
         yield 6
 
 
+def nested_except_gh3666(a=False, b=False):
+    """
+    >>> print(nested_except_gh3666())
+    A
+    >>> print(nested_except_gh3666(a=True))
+    B-V
+    >>> print(nested_except_gh3666(a=True, b=True))
+    B-V-T
+    """
+    try:
+        if a:
+            raise ValueError
+        return "A"
+    except TypeError as exc:
+        return "A-T"
+    except ValueError as exc:
+        try:
+            if b:
+                raise TypeError
+            return "B-V"
+        except ValueError as exc:
+            return "B-V-V"
+        except TypeError as exc:
+            return "B-V-T"
+
+
 ### Py3 feature tests
 
 def print_function(*args):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/run/fused_types.pyx 
new/Cython-0.29.20/tests/run/fused_types.pyx
--- old/Cython-0.29.19/tests/run/fused_types.pyx        2020-05-19 
10:45:14.000000000 +0200
+++ new/Cython-0.29.20/tests/run/fused_types.pyx        2020-06-10 
15:13:19.000000000 +0200
@@ -400,3 +400,27 @@
         return x
     else:
         return 2 * x
+
+
+### see GH3642 - presence of cdef inside "unrelated" caused a type to be 
incorrectly inferred
+cdef unrelated(cython.floating x):
+    cdef cython.floating t = 1
+    return t
+
+cdef handle_float(float* x): return 'float'
+
+cdef handle_double(double* x): return 'double'
+
+def convert_to_ptr(cython.floating x):
+    """
+    >>> convert_to_ptr(1.0)
+    'double'
+    >>> convert_to_ptr['double'](1.0)
+    'double'
+    >>> convert_to_ptr['float'](1.0)
+    'float'
+    """
+    if cython.floating is float:
+        return handle_float(&x)
+    elif cython.floating is double:
+        return handle_double(&x)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/Cython-0.29.19/tests/run/verbatiminclude.pyx 
new/Cython-0.29.20/tests/run/verbatiminclude.pyx
--- old/Cython-0.29.19/tests/run/verbatiminclude.pyx    2018-09-22 
16:18:56.000000000 +0200
+++ new/Cython-0.29.20/tests/run/verbatiminclude.pyx    2020-06-10 
15:13:19.000000000 +0200
@@ -25,9 +25,9 @@
 
 cdef extern from "Python.h":
     """
-    #define Py_SET_SIZE(obj, size)  Py_SIZE((obj)) = (size)
+    #define my_SET_SIZE(obj, size)  __Pyx_SET_SIZE(obj, size)
     """
-    void Py_SET_SIZE(object, Py_ssize_t)
+    void my_SET_SIZE(object, Py_ssize_t)
 
 
 def test_square(x):
@@ -59,4 +59,4 @@
 def test_set_size(x, size):
     # This function manipulates Python objects in a bad way, so we
     # do not call it. The real test is that it compiles.
-    Py_SET_SIZE(x, size)
+    my_SET_SIZE(x, size)


Reply via email to