diff options
author | da-woods <dw-git@d-woods.co.uk> | 2022-05-16 12:03:35 +0100 |
---|---|---|
committer | Stefan Behnel <stefan_ml@behnel.de> | 2022-05-16 13:16:09 +0200 |
commit | c100f5e8245378aab8555d44f50c695567dc2417 (patch) | |
tree | e3d2217b2342183a0409c96199c2fb84d0dcc2eb | |
parent | 4e23f3e44daf73153904d9599ed696cbf8ae704f (diff) | |
download | cython-c100f5e8245378aab8555d44f50c695567dc2417.tar.gz |
Remove ".__contains__" -> "PySequence_Contains" slot mappings for known builtin types (GH-4792)
They prevent explicitly calling the base-class __contains__.
Closes https://github.com/cython/cython/issues/4785
-rw-r--r-- | Cython/Compiler/Builtin.py | 15 | ||||
-rw-r--r-- | tests/run/builtin_subtype_methods_T653.pyx | 47 |
2 files changed, 52 insertions, 10 deletions
diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py index 5fa717507..e0d203ae0 100644 --- a/Cython/Compiler/Builtin.py +++ b/Cython/Compiler/Builtin.py @@ -271,12 +271,10 @@ builtin_types_table = [ ]), ("bytearray", "PyByteArray_Type", [ ]), - ("bytes", "PyBytes_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), - BuiltinMethod("join", "TO", "O", "__Pyx_PyBytes_Join", + ("bytes", "PyBytes_Type", [BuiltinMethod("join", "TO", "O", "__Pyx_PyBytes_Join", utility_code=UtilityCode.load("StringJoin", "StringTools.c")), ]), - ("str", "PyString_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), - BuiltinMethod("join", "TO", "O", "__Pyx_PyString_Join", + ("str", "PyString_Type", [BuiltinMethod("join", "TO", "O", "__Pyx_PyString_Join", builtin_return_type='basestring', utility_code=UtilityCode.load("StringJoin", "StringTools.c")), ]), @@ -284,11 +282,9 @@ builtin_types_table = [ BuiltinMethod("join", "TO", "T", "PyUnicode_Join"), ]), - ("tuple", "PyTuple_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), - ]), + ("tuple", "PyTuple_Type", []), - ("list", "PyList_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), - BuiltinMethod("insert", "TzO", "r", "PyList_Insert"), + ("list", "PyList_Type", [BuiltinMethod("insert", "TzO", "r", "PyList_Insert"), BuiltinMethod("reverse", "T", "r", "PyList_Reverse"), BuiltinMethod("append", "TO", "r", "__Pyx_PyList_Append", utility_code=UtilityCode.load("ListAppend", "Optimize.c")), @@ -326,8 +322,7 @@ builtin_types_table = [ ]), # ("file", "PyFile_Type", []), # not in Py3 - ("set", "PySet_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"), - BuiltinMethod("clear", "T", "r", "PySet_Clear"), + ("set", "PySet_Type", [BuiltinMethod("clear", "T", "r", "PySet_Clear"), # discard() and remove() have a special treatment for unhashable values BuiltinMethod("discard", "TO", "r", "__Pyx_PySet_Discard", utility_code=UtilityCode.load("py_set_discard", "Optimize.c")), diff --git a/tests/run/builtin_subtype_methods_T653.pyx b/tests/run/builtin_subtype_methods_T653.pyx index bcfda81f0..e02326598 100644 --- a/tests/run/builtin_subtype_methods_T653.pyx +++ b/tests/run/builtin_subtype_methods_T653.pyx @@ -4,7 +4,21 @@ cimport cython +# The "contains" tests relate to GH-4785 - replacing the method +# call with PySequence_Contains was causing infinite recursion +# for some classes + cdef class MyList(list): + """ + >>> l = MyList() + >>> l.__contains__(1) + MyList.__contains__ + False + >>> l.append(1) + >>> l.__contains__(1) + MyList.__contains__ + True + """ def test_append(self, x): """ >>> l = MyList() @@ -18,7 +32,13 @@ cdef class MyList(list): """ self.append(x) + def __contains__(self, value): + print "MyList.__contains__" + return list.__contains__(self, value) # probably optimized + cdef class MyDict(dict): + # tests for __contains__ are in the global __doc__ to version-check a PyPy bug + @cython.test_assert_path_exists("//ComprehensionNode//AttributeNode", "//ComprehensionNode//AttributeNode[@attribute='items']") @cython.test_fail_if_path_exists("//ComprehensionNode//CMethodSelfCloneNode") @@ -40,6 +60,19 @@ cdef class MyDict(dict): l.sort() return l + def __contains__(self, key): + print "MyDict.__contains__" + return dict.__contains__(self, key) + +import sys +pypy_version = getattr(sys, 'pypy_version_info', None) +if not (pypy_version and pypy_version < (7, 3, 10)): + __doc__ = """ + >>> MyDict(a=1).__contains__("a") + MyDict.__contains__ + True + """ + @cython.final cdef class MyDictFinal(dict): @cython.test_assert_path_exists("//ComprehensionNode//CMethodSelfCloneNode") @@ -155,3 +188,17 @@ cdef class MyDictOverride2(MyDict): l = [ v for v in self.values() ] l.sort() return l + +class MyBytes(bytes): + """ + >>> mb = MyBytes(b"abc") + >>> mb.__contains__(b"a") + MyBytes.__contains__ + True + >>> mb.__contains__(b"z") + MyBytes.__contains__ + False + """ + def __contains__(self, value): + print "MyBytes.__contains__" + return bytes.__contains__(self, value) |