summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorda-woods <dw-git@d-woods.co.uk>2022-05-16 12:03:35 +0100
committerStefan Behnel <stefan_ml@behnel.de>2022-05-16 13:16:09 +0200
commitc100f5e8245378aab8555d44f50c695567dc2417 (patch)
treee3d2217b2342183a0409c96199c2fb84d0dcc2eb
parent4e23f3e44daf73153904d9599ed696cbf8ae704f (diff)
downloadcython-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.py15
-rw-r--r--tests/run/builtin_subtype_methods_T653.pyx47
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)