From: Lisandro Dalcin Date: Wed, 11 Nov 2009 15:11:31 +0000 (-0200) Subject: implementation of 'not in' is broken (ticket #455) X-Git-Tag: 0.12.rc0~3 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=1175bb684d31f5b2e8c1a02cdd2f584c1cc02ace;p=cython.git implementation of 'not in' is broken (ticket #455) --- diff --git a/Cython/Compiler/ExprNodes.py b/Cython/Compiler/ExprNodes.py index bc05047b..353a78e0 100644 --- a/Cython/Compiler/ExprNodes.py +++ b/Cython/Compiler/ExprNodes.py @@ -5226,9 +5226,14 @@ class CmpNode(object): coerce_result = "__Pyx_PyBool_FromLong" else: coerce_result = "" - if 'not' in op: negation = "!" - else: negation = "" + if 'not' in op: + negation = "!" + else: + negation = "" if op == 'in' or op == 'not_in': + assert not coerce_result + if op == 'not_in': + negation = "if (likely(%s != -1)) %s = !%s; " % ((result_code,)*3) if operand2.type is dict_type: code.globalstate.use_utility_code( raise_none_iter_error_utility_code) @@ -5237,23 +5242,22 @@ class CmpNode(object): code.error_goto(self.pos)) code.putln("} else {") code.putln( - "%s = %s(%sPyDict_Contains(%s, %s)); %s" % ( + "%s = PyDict_Contains(%s, %s); %s%s" % ( result_code, - coerce_result, - negation, operand2.py_result(), operand1.py_result(), + negation, code.error_goto_if_neg(result_code, self.pos))) code.putln("}") else: code.putln( - "%s = %s(%sPySequence_Contains(%s, %s)); %s" % ( + "%s = PySequence_Contains(%s, %s); %s%s" % ( result_code, - coerce_result, - negation, operand2.py_result(), operand1.py_result(), + negation, code.error_goto_if_neg(result_code, self.pos))) + elif (operand1.type.is_pyobject and op not in ('is', 'is_not')): code.putln("%s = PyObject_RichCompare(%s, %s, %s); %s" % ( diff --git a/tests/run/contains_T455.pyx b/tests/run/contains_T455.pyx new file mode 100644 index 00000000..669f89c1 --- /dev/null +++ b/tests/run/contains_T455.pyx @@ -0,0 +1,82 @@ +def in_sequence(x, seq): + """ + >>> in_sequence(1, []) + False + >>> in_sequence(1, ()) + False + >>> in_sequence(1, {}) + False + >>> in_sequence(1, [1]) + True + >>> in_sequence(1, (1,)) + True + >>> in_sequence(1, {1:None}) + True + + >>> in_sequence(1, None) + Traceback (most recent call last): + ... + TypeError: argument of type 'NoneType' is not iterable + + >>> in_sequence(1, 1) + Traceback (most recent call last): + ... + TypeError: argument of type 'int' is not iterable + """ + return x in seq + +def not_in_sequence(x, seq): + """ + >>> not_in_sequence(1, []) + True + >>> not_in_sequence(1, ()) + True + >>> not_in_sequence(1, {}) + True + >>> not_in_sequence(1, [1]) + False + >>> not_in_sequence(1, (1,)) + False + >>> not_in_sequence(1, {1:None}) + False + + >>> not_in_sequence(1, None) + Traceback (most recent call last): + ... + TypeError: argument of type 'NoneType' is not iterable + + >>> not_in_sequence(1, 1) + Traceback (most recent call last): + ... + TypeError: argument of type 'int' is not iterable + """ + return x not in seq + + +def in_dict(k, dict dct): + """ + >>> in_dict(1, {}) + False + >>> in_dict(1, {1:None}) + True + + >>> in_dict(1, None) + Traceback (most recent call last): + ... + TypeError: 'NoneType' object is not iterable + """ + return k in dct + +def not_in_dict(k, dict dct): + """ + >>> not_in_dict(1, {}) + True + >>> not_in_dict(1, {1:None}) + False + + >>> not_in_dict(1, None) + Traceback (most recent call last): + ... + TypeError: 'NoneType' object is not iterable + """ + return k not in dct