From: DongHun Kwak Date: Thu, 31 Dec 2020 03:08:50 +0000 (+0900) Subject: Imported Upstream version 0.28.3 X-Git-Tag: upstream/0.28.3^0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=95374c16a5a4872f9415865d0d28354bb1bb012e;p=platform%2Fupstream%2Fpython3-cython.git Imported Upstream version 0.28.3 --- diff --git a/CHANGES.rst b/CHANGES.rst index 19f3323..45b7055 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -2,6 +2,21 @@ Cython Changelog ================ +0.28.3 (2018-05-27) +=================== + +Bugs fixed +---------- + +* Set iteration was broken in non-CPython since 0.28. + +* ``UnicodeEncodeError`` in Py2 when ``%s`` formatting is optimised for + unicode strings. (Github issue #2276) + +* Work around a crash bug in g++ 4.4.x by disabling the size reduction setting + of the module init function in this version. (Github issue #2235) + + 0.28.2 (2018-04-13) =================== @@ -14,7 +29,7 @@ Features added ``libcpp.string``. Patch by Alex Huszagh. (Github issue #2123) * The C++11 methods ``reserve()`` and ``bucket_count()`` are declared for - ``std::unordered_map``. Patch by Valentin Valls. (Github issue #2168) + ``libcpp.unordered_map``. Patch by Valentin Valls. (Github issue #2168) Bugs fixed ---------- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index b3dbd9d..2c538df 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -3164,7 +3164,7 @@ class FormattedValueNode(ExprNode): c_format_spec = None find_conversion_func = { - 's': 'PyObject_Str', + 's': 'PyObject_Unicode', 'r': 'PyObject_Repr', 'a': 'PyObject_ASCII', # NOTE: mapped to PyObject_Repr() in Py2 }.get @@ -11053,9 +11053,8 @@ class CBinopNode(BinopNode): cpp_type = None if type1.is_cpp_class or type1.is_ptr: cpp_type = type1.find_cpp_operation_type(self.operator, type2) - # FIXME: handle the reversed case? - #if cpp_type is None and (type2.is_cpp_class or type2.is_ptr): - # cpp_type = type2.find_cpp_operation_type(self.operator, type1) + if cpp_type is None and (type2.is_cpp_class or type2.is_ptr): + cpp_type = type2.find_cpp_operation_type(self.operator, type1) # FIXME: do we need to handle other cases here? return cpp_type diff --git a/Cython/Compiler/ModuleNode.py b/Cython/Compiler/ModuleNode.py index bd1db3a..9449502 100644 --- a/Cython/Compiler/ModuleNode.py +++ b/Cython/Compiler/ModuleNode.py @@ -707,7 +707,7 @@ class ModuleNode(Nodes.Node, Nodes.BlockNode): code.putln('static PyObject *%s = NULL;' % env.module_cname) code.putln('static PyObject *%s;' % env.module_dict_cname) code.putln('static PyObject *%s;' % Naming.builtins_cname) - code.putln('static PyObject *%s;' % Naming.cython_runtime_cname) + code.putln('static PyObject *%s = NULL;' % Naming.cython_runtime_cname) code.putln('static PyObject *%s;' % Naming.empty_tuple) code.putln('static PyObject *%s;' % Naming.empty_bytes) code.putln('static PyObject *%s;' % Naming.empty_unicode) diff --git a/Cython/Compiler/Symtab.py b/Cython/Compiler/Symtab.py index 21e89e7..4fe903c 100644 --- a/Cython/Compiler/Symtab.py +++ b/Cython/Compiler/Symtab.py @@ -907,10 +907,28 @@ class Scope(object): if res is not None: return res function = self.lookup("operator%s" % operator) - if function is None: + function_alternatives = [] + if function is not None: + function_alternatives = function.all_alternatives() + + # look-up nonmember methods listed within a class + method_alternatives = [] + if len(operands)==2: # binary operators only + for n in range(2): + if operands[n].type.is_cpp_class: + obj_type = operands[n].type + method = obj_type.scope.lookup("operator%s" % operator) + if method is not None: + method_alternatives += method.all_alternatives() + + if (not method_alternatives) and (not function_alternatives): return None + + # select the unique alternatives + all_alternatives = list(set(method_alternatives + function_alternatives)) + return PyrexTypes.best_match([arg.type for arg in operands], - function.all_alternatives()) + all_alternatives) def lookup_operator_for_types(self, pos, operator, types): from .Nodes import Node diff --git a/Cython/Shadow.py b/Cython/Shadow.py index 8d68bc0..0f14a58 100644 --- a/Cython/Shadow.py +++ b/Cython/Shadow.py @@ -1,7 +1,7 @@ # cython.* namespace for pure mode. from __future__ import absolute_import -__version__ = "0.28.2" +__version__ = "0.28.3" try: from __builtin__ import basestring diff --git a/Cython/Utility/Exceptions.c b/Cython/Utility/Exceptions.c index 1774156..8628e3a 100644 --- a/Cython/Utility/Exceptions.c +++ b/Cython/Utility/Exceptions.c @@ -617,6 +617,12 @@ static int __Pyx_CLineForTraceback(CYTHON_UNUSED PyThreadState *tstate, int c_li #if CYTHON_COMPILING_IN_CPYTHON PyObject **cython_runtime_dict; #endif + + if (unlikely(!${cython_runtime_cname})) { + // Very early error where the runtime module is not set up yet. + return c_line; + } + __Pyx_ErrFetchInState(tstate, &ptype, &pvalue, &ptraceback); #if CYTHON_COMPILING_IN_CPYTHON diff --git a/Cython/Utility/ModuleSetupCode.c b/Cython/Utility/ModuleSetupCode.c index 2aeabd2..c1ba400 100644 --- a/Cython/Utility/ModuleSetupCode.c +++ b/Cython/Utility/ModuleSetupCode.c @@ -558,6 +558,7 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #define PyString_Type PyUnicode_Type #define PyString_Check PyUnicode_Check #define PyString_CheckExact PyUnicode_CheckExact + #define PyObject_Unicode PyObject_Str #endif #if PY_MAJOR_VERSION >= 3 @@ -668,7 +669,8 @@ static CYTHON_INLINE void * PyThread_tss_get(Py_tss_t *key) { #ifndef CYTHON_SMALL_CODE #if defined(__clang__) #define CYTHON_SMALL_CODE -#elif defined(__GNUC__) +#elif defined(__GNUC__) && (!(defined(__cplusplus)) || (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ > 4))) + // At least g++ 4.4.7 can generate crashing code with this option. (GH #2235) #define CYTHON_SMALL_CODE __attribute__((optimize("Os"))) #else #define CYTHON_SMALL_CODE diff --git a/Cython/Utility/Optimize.c b/Cython/Utility/Optimize.c index fa5a8d5..13277ab 100644 --- a/Cython/Utility/Optimize.c +++ b/Cython/Utility/Optimize.c @@ -438,17 +438,17 @@ static CYTHON_INLINE PyObject* __Pyx_set_iterator(PyObject* iterable, int is_set #if CYTHON_COMPILING_IN_CPYTHON is_set = is_set || likely(PySet_CheckExact(iterable) || PyFrozenSet_CheckExact(iterable)); *p_source_is_set = is_set; - if (unlikely(!is_set)) - return PyObject_GetIter(iterable); - *p_orig_length = PySet_Size(iterable); - Py_INCREF(iterable); - return iterable; + if (likely(is_set)) { + *p_orig_length = PySet_Size(iterable); + Py_INCREF(iterable); + return iterable; + } #else (void)is_set; *p_source_is_set = 0; +#endif *p_orig_length = 0; return PyObject_GetIter(iterable); -#endif } static CYTHON_INLINE int __Pyx_set_iter_next( @@ -462,7 +462,7 @@ static CYTHON_INLINE int __Pyx_set_iter_next( } (void)orig_length; (void)ppos; - return 0; + return 1; } #if CYTHON_COMPILING_IN_CPYTHON if (unlikely(PySet_GET_SIZE(iter_obj) != orig_length)) { @@ -480,9 +480,9 @@ static CYTHON_INLINE int __Pyx_set_iter_next( Py_INCREF(*value); return 1; } - return 0; } #endif + return 0; } /////////////// py_set_discard_unhashable /////////////// diff --git a/Cython/Utility/TypeConversion.c b/Cython/Utility/TypeConversion.c index 734e293..bf8d3b1 100644 --- a/Cython/Utility/TypeConversion.c +++ b/Cython/Utility/TypeConversion.c @@ -84,7 +84,7 @@ static CYTHON_INLINE size_t __Pyx_Py_UNICODE_strlen(const Py_UNICODE *u) { #define __Pyx_NewRef(obj) (Py_INCREF(obj), obj) #define __Pyx_Owned_Py_None(b) __Pyx_NewRef(Py_None) -#define __Pyx_PyBool_FromLong(b) ((b) ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False)) +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b); static CYTHON_INLINE int __Pyx_PyObject_IsTrue(PyObject*); static CYTHON_INLINE PyObject* __Pyx_PyNumber_IntOrLong(PyObject* x); @@ -402,6 +402,12 @@ static CYTHON_INLINE Py_ssize_t __Pyx_PyIndex_AsSsize_t(PyObject* b) { return ival; } + +static CYTHON_INLINE PyObject * __Pyx_PyBool_FromLong(long b) { + return b ? __Pyx_NewRef(Py_True) : __Pyx_NewRef(Py_False); +} + + static CYTHON_INLINE PyObject * __Pyx_PyInt_FromSize_t(size_t ival) { return PyInt_FromSize_t(ival); } diff --git a/docs/CONTRIBUTING.txt b/docs/CONTRIBUTING.txt new file mode 100644 index 0000000..90c2fe9 --- /dev/null +++ b/docs/CONTRIBUTING.txt @@ -0,0 +1,11 @@ +Welcome, and thank you for your interest in contributing! +========================================================= + +If you are looking for a good way to contribute to the Cython project, please +- have a look at the [Cython Hacker Guide](https://github.com/cython/cython/wiki/HackerGuide) +- look through the [issues that need help](https://github.com/cython/cython/issues?q=is%3Aissue+is%3Aopen+view+label%3A%22help+wanted%22) +- look through the [issues that are a good entry point for beginners](https://github.com/cython/cython/issues?q=is%3Aissue+is%3Aopen+view+label%3A%22good+first+issue%22) + +If you have code that you want to contribute, please make sure that it +- includes tests in the `tests/` directory (see the [Hacker Guide on Testing](https://github.com/cython/cython/wiki/HackerGuide#the-test-suite)) +- comes in form of a pull request diff --git a/docs/src/userguide/wrapping_CPlusPlus.rst b/docs/src/userguide/wrapping_CPlusPlus.rst index eb6301b..b1e9a6b 100644 --- a/docs/src/userguide/wrapping_CPlusPlus.rst +++ b/docs/src/userguide/wrapping_CPlusPlus.rst @@ -321,6 +321,10 @@ Cython uses C++ naming for overloading operators:: Foo operator-(Foo) int operator*(Foo) int operator/(int) + int operator*(int, Foo) # allows 1*Foo() + # nonmember operators can also be specified outside the class + double operator/(double, Foo) + cdef Foo foo = new Foo() @@ -330,6 +334,13 @@ Cython uses C++ naming for overloading operators:: x = foo * foo2 x = foo / 1 + x = foo[0] * foo2 + x = foo[0] / 1 + x = 1*foo[0] + + cdef double y + y = 2.0/foo[0] + Note that if one has *pointers* to C++ objects, dereferencing must be done to avoid doing pointer arithmetic rather than arithmetic on the objects themselves:: diff --git a/tests/run/cpp_bool_template_return.pyx b/tests/run/cpp_bool_template_return.pyx new file mode 100644 index 0000000..fced8ad --- /dev/null +++ b/tests/run/cpp_bool_template_return.pyx @@ -0,0 +1,16 @@ +# tag: cpp + +from libcpp cimport bool + +cdef extern from "cpp_templates_helper.h": + cdef cppclass BinaryAnd[T1, T2]: + @staticmethod + T1 call(T1 x, T2 y) + + +def test_compound_bool_return(bool x, bool y): + """ + >>> test_compound_bool_return(True, False) + False + """ + return BinaryAnd[bool, bool].call(x, y) diff --git a/tests/run/cpp_operators.pyx b/tests/run/cpp_operators.pyx index e1877d1..aca865f 100644 --- a/tests/run/cpp_operators.pyx +++ b/tests/run/cpp_operators.pyx @@ -27,18 +27,29 @@ cdef extern from "cpp_operators_helper.h" nogil: const_char* operator--(int) const_char* operator+(int) + const_char* operator+(int,const TestOps&) const_char* operator-(int) + const_char* operator-(int,const TestOps&) const_char* operator*(int) + # deliberately omitted operator* to test case where only defined outside class const_char* operator/(int) + const_char* operator/(int,const TestOps&) const_char* operator%(int) + const_char* operator%(int,const TestOps&) const_char* operator|(int) + const_char* operator|(int,const TestOps&) const_char* operator&(int) + const_char* operator&(int,const TestOps&) const_char* operator^(int) + const_char* operator^(int,const TestOps&) const_char* operator,(int) + const_char* operator,(int,const TestOps&) const_char* operator<<(int) + const_char* operator<<(int,const TestOps&) const_char* operator>>(int) + const_char* operator>>(int,const TestOps&) const_char* operator==(int) const_char* operator!=(int) @@ -49,6 +60,23 @@ cdef extern from "cpp_operators_helper.h" nogil: const_char* operator[](int) const_char* operator()(int) + + # Defining the operator outside the class does work + # but doesn't help when importing from pxd files + # (they don't get imported) + const_char* operator+(float,const TestOps&) + # deliberately omitted operator- to test case where only defined in class + const_char* operator*(float,const TestOps&) + const_char* operator/(float,const TestOps&) + const_char* operator%(float,const TestOps&) + + const_char* operator|(float,const TestOps&) + const_char* operator&(float,const TestOps&) + const_char* operator^(float,const TestOps&) + const_char* operator,(float,const TestOps&) + + const_char* operator<<(float,const TestOps&) + const_char* operator>>(float,const TestOps&) cdef cppclass TruthClass: TruthClass() @@ -129,6 +157,63 @@ def test_binop(): out(x, typeof(x)) del t +def test_nonmember_binop(): + """ + >>> test_nonmember_binop() + nonmember binary + [const_char *] + nonmember binary - [const_char *] + nonmember binary / [const_char *] + nonmember binary % [const_char *] + nonmember binary & [const_char *] + nonmember binary | [const_char *] + nonmember binary ^ [const_char *] + nonmember binary << [const_char *] + nonmember binary >> [const_char *] + nonmember binary COMMA [const_char *] + nonmember binary2 + [const_char *] + nonmember binary2 * [const_char *] + nonmember binary2 / [const_char *] + nonmember binary2 % [const_char *] + nonmember binary2 & [const_char *] + nonmember binary2 | [const_char *] + nonmember binary2 ^ [const_char *] + nonmember binary2 << [const_char *] + nonmember binary2 >> [const_char *] + nonmember binary2 COMMA [const_char *] + """ + + cdef TestOps* t = new TestOps() + out(1 + t[0], typeof(1 + t[0])) + out(1 - t[0], typeof(1 - t[0])) + # * deliberately omitted + out(1 / t[0], typeof(1 / t[0])) + out(1 % t[0], typeof(1 % t[0])) + out(1 & t[0], typeof(1 & t[0])) + out(1 | t[0], typeof(1 | t[0])) + out(1 ^ t[0], typeof(1 ^ t[0])) + out(1 << t[0], typeof(1 << t[0])) + out(1 >> t[0], typeof(1 >> t[0])) + + x = cython.operator.comma(1, t[0]) + out(x, typeof(x)) + + # now test float operators defined outside class + out(1. + t[0], typeof(1. + t[0])) + # operator - deliberately omitted + out(1. * t[0], typeof(1. * t[0])) + out(1. / t[0], typeof(1. / t[0])) + out(1. % t[0], typeof(1. % t[0])) + out(1. & t[0], typeof(1. & t[0])) + out(1. | t[0], typeof(1. | t[0])) + out(1. ^ t[0], typeof(1. ^ t[0])) + out(1. << t[0], typeof(1. << t[0])) + out(1. >> t[0], typeof(1. >> t[0])) + + # for some reason we need a cdef here - not sure this is quite right + y = cython.operator.comma(1., t[0]) + out(y, typeof(y)) + del t + def test_cmp(): """ >>> test_cmp() diff --git a/tests/run/cpp_operators_helper.h b/tests/run/cpp_operators_helper.h index 36685c5..5ae21ff 100644 --- a/tests/run/cpp_operators_helper.h +++ b/tests/run/cpp_operators_helper.h @@ -1,6 +1,8 @@ #define UN_OP(op) const char* operator op () { return "unary "#op; } #define POST_UN_OP(op) const char* operator op (int x) { x++; return "post "#op; } #define BIN_OP(op) const char* operator op (int x) { x++; return "binary "#op; } +#define NONMEMBER_BIN_OP(op) const char* operator op (int x, const TestOps&) { x++; return "nonmember binary "#op; } +#define NONMEMBER_BIN_OP2(op) const char* operator op (double x, const TestOps&) { x++; return "nonmember binary2 "#op; } #define COMMA , @@ -46,6 +48,34 @@ public: }; +NONMEMBER_BIN_OP(+) +NONMEMBER_BIN_OP(-) +NONMEMBER_BIN_OP(*) +NONMEMBER_BIN_OP(/) +NONMEMBER_BIN_OP(%) + +NONMEMBER_BIN_OP(<<) +NONMEMBER_BIN_OP(>>) + +NONMEMBER_BIN_OP(|) +NONMEMBER_BIN_OP(&) +NONMEMBER_BIN_OP(^) +NONMEMBER_BIN_OP(COMMA) + +NONMEMBER_BIN_OP2(+) +NONMEMBER_BIN_OP2(-) +NONMEMBER_BIN_OP2(*) +NONMEMBER_BIN_OP2(/) +NONMEMBER_BIN_OP2(%) + +NONMEMBER_BIN_OP2(<<) +NONMEMBER_BIN_OP2(>>) + +NONMEMBER_BIN_OP2(|) +NONMEMBER_BIN_OP2(&) +NONMEMBER_BIN_OP2(^) +NONMEMBER_BIN_OP2(COMMA) + class TruthClass { public: TruthClass() : value(false) {} diff --git a/tests/run/cpp_templates_helper.h b/tests/run/cpp_templates_helper.h index 8973e6c..629ac65 100644 --- a/tests/run/cpp_templates_helper.h +++ b/tests/run/cpp_templates_helper.h @@ -44,3 +44,9 @@ class Div { public: static T half(T value) { return value / 2; } }; + +template +class BinaryAnd { +public: + static T1 call(T1 x, T2 y) { return x & y; } +}; diff --git a/tests/run/fstring.pyx b/tests/run/fstring.pyx index b12387d..7abbb4f 100644 --- a/tests/run/fstring.pyx +++ b/tests/run/fstring.pyx @@ -500,3 +500,16 @@ def generated_fstring(int i, unicode u not None, o): u, u, u, u, o, o, o, o, ) + + +@cython.test_assert_path_exists( + "//FormattedValueNode", + "//JoinedStrNode", +) +def percent_s_unicode(u, int i): + u""" + >>> u = u'x\u0194z' + >>> print(percent_s_unicode(u, 12)) + x\u0194z-12 + """ + return u"%s-%d" % (u, i) diff --git a/tests/run/libcpp_all.pyx b/tests/run/libcpp_all.pyx index 45983ba..2930807 100644 --- a/tests/run/libcpp_all.pyx +++ b/tests/run/libcpp_all.pyx @@ -94,6 +94,7 @@ cdef const_vector_to_list(const vector[double]& cv): cython.operator.preincrement(iter) return lst + cdef double dmax = numeric_limits[double].max() cdef double dmin = numeric_limits[double].min() cdef double deps = numeric_limits[double].epsilon() @@ -124,4 +125,23 @@ def convert_to_vector(I): """ cdef vector[int] x = I - + +def complex_operators(): + """ + >>> complex_operators() + [-1.0, 0.0, 0.0, 2.0, 0.0, 2.0] + """ + cdef libcpp.complex.complex[double] a = libcpp.complex.complex[double](0.0,1.0) + cdef libcpp.complex.complex[double] r1=a*a + cdef libcpp.complex.complex[double] r2=a*2.0 + cdef libcpp.complex.complex[double] r3=2.0*a + return [r1.real(), r1.imag(), r2.real(), r2.imag(), r3.real(), r3.imag()] + +def pair_comparison(): + """ + >>> pair_comparison() + [False, True, False, True, False] + """ + cdef pair[double, double] p1 = pair[double, double](1.0,2.0) + cdef pair[double, double] p2 = pair[double, double](2.0,2.0) + return [p1==p2,p1==p1,p1>p2,p1p2]