BuiltinAttribute('imag', 'cval.imag', field_type = PyrexTypes.c_double_type),
]),
- ("bytes", "PyBytes_Type", []),
- ("str", "PyString_Type", []),
- ("unicode", "PyUnicode_Type", [BuiltinMethod("join", "TO", "T", "PyUnicode_Join"),
+ ("bytes", "PyBytes_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"),
+ ]),
+ ("str", "PyString_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"),
+ ]),
+ ("unicode", "PyUnicode_Type", [BuiltinMethod("__contains__", "TO", "b", "PyUnicode_Contains"),
+ BuiltinMethod("join", "TO", "T", "PyUnicode_Join"),
]),
- ("tuple", "PyTuple_Type", []),
+ ("tuple", "PyTuple_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"),
+ ]),
- ("list", "PyList_Type", [BuiltinMethod("insert", "TzO", "r", "PyList_Insert"),
+ ("list", "PyList_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"),
+ 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")),
]),
- ("dict", "PyDict_Type", [BuiltinMethod("items", "T", "O", "__Pyx_PyDict_Items",
+ ("dict", "PyDict_Type", [BuiltinMethod("__contains__", "TO", "b", "PyDict_Contains"),
+ BuiltinMethod("items", "T", "O", "__Pyx_PyDict_Items",
utility_code=UtilityCode.load("py_dict_items", "Builtins.c")),
BuiltinMethod("keys", "T", "O", "__Pyx_PyDict_Keys",
utility_code=UtilityCode.load("py_dict_keys", "Builtins.c")),
]),
# ("file", "PyFile_Type", []), # not in Py3
- ("set", "PySet_Type", [BuiltinMethod("clear", "T", "r", "PySet_Clear",
+ ("set", "PySet_Type", [BuiltinMethod("__contains__", "TO", "b", "PySequence_Contains"),
+ BuiltinMethod("clear", "T", "r", "PySet_Clear",
utility_code = py_set_utility_code),
# discard() and remove() have a special treatment for unhashable values
# BuiltinMethod("discard", "TO", "r", "PySet_Discard",
if not entry:
entry = env.lookup(self.name)
if entry and entry.is_type:
- if entry.type.is_extension_type: # or entry.type.is_builtin_type:
+ if entry.type.is_extension_type or entry.type.is_builtin_type:
return entry.type
return None
else:
arg = CloneNode(self.self)
arg = self.coerced_self = arg.coerce_to(formal_arg.type, env)
+ elif formal_arg.type.is_builtin_type:
+ # special case: unbound methods of builtins accept subtypes
+ arg = arg.coerce_to(formal_arg.type, env)
+ if arg.type.is_builtin_type and isinstance(arg, PyTypeTestNode):
+ arg.exact_builtin_type = False
args[0] = arg
# Coerce arguments
entry = type.scope.lookup_here(self.attribute)
if entry and entry.is_cmethod:
if type.is_builtin_type:
+ if not self.is_called:
+ # must handle this as Python object
+ return None
ubcm_entry = entry
else:
# Create a temporary entry describing the C method
if module_scope:
entry = module_scope.lookup_here(self.attribute)
if entry and entry.is_type:
- if entry.type.is_extension_type: # or entry.type.is_builtin_type:
+ if entry.type.is_extension_type or entry.type.is_builtin_type:
return entry.type
return None
# object is an instance of a particular extension type.
# This node borrows the result of its argument node.
+ exact_builtin_type = True
+
def __init__(self, arg, dst_type, env, notnone=False):
# The arg is know to be a Python object, and
# the dst_type is known to be an extension type.
def generate_result_code(self, code):
if self.type.typeobj_is_available():
- if not self.type.is_builtin_type:
- code.globalstate.use_utility_code(UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c"))
- code.putln(
- "if (!(%s)) %s" % (
- self.type.type_test_code(self.arg.py_result(), self.notnone),
- code.error_goto(self.pos)))
+ if self.type.is_builtin_type:
+ type_test = self.type.type_test_code(
+ self.arg.py_result(),
+ self.notnone, exact=self.exact_builtin_type)
+ else:
+ type_test = self.type.type_test_code(
+ self.arg.py_result(), self.notnone)
+ code.globalstate.use_utility_code(
+ UtilityCode.load_cached("ExtTypeTest", "ObjectHandling.c"))
+ code.putln("if (!(%s)) %s" % (
+ type_test, code.error_goto(self.pos)))
else:
error(self.pos, "Cannot test type of extern C class "
"without type object name specification")
def isinstance_code(self, arg):
return '%s(%s)' % (self.type_check_function(exact=False), arg)
- def type_test_code(self, arg, notnone=False):
- type_check = self.type_check_function(exact=True)
+ def type_test_code(self, arg, notnone=False, exact=True):
+ type_check = self.type_check_function(exact=exact)
check = 'likely(%s(%s))' % (type_check, arg)
if not notnone:
check += '||((%s) == Py_None)' % arg
def declare_cfunction(self, name, type, pos,
cname = None, visibility = 'private', api = 0, in_pxd = 0,
defining = 0, modifiers = (), utility_code = None):
- if get_special_method_signature(name):
+ if get_special_method_signature(name) and not self.parent_type.is_builtin_type:
error(pos, "Special methods must be declared with 'def', not 'cdef'")
args = type.args
if not args:
--- /dev/null
+# mode: run
+# tag: special_method
+
+cimport cython
+
+text = u'ab jd sdflk as sa sadas asdas fsdf '
+
+
+@cython.test_fail_if_path_exists(
+ "//CoerceFromPyTypeNode")
+@cython.test_assert_path_exists(
+ "//CoerceToPyTypeNode",
+ "//AttributeNode",
+ "//AttributeNode[@entry.cname = 'PyUnicode_Contains']")
+def unicode_contains(unicode s, substring):
+ """
+ >>> unicode_contains(text, 'fl')
+ True
+ >>> unicode_contains(text, 'XYZ')
+ False
+ >>> unicode_contains(None, 'XYZ')
+ Traceback (most recent call last):
+ AttributeError: 'NoneType' object has no attribute '__contains__'
+ """
+ return s.__contains__(substring)
+
+
+@cython.test_fail_if_path_exists(
+ "//CoerceFromPyTypeNode")
+@cython.test_assert_path_exists(
+# "//CoerceToPyTypeNode",
+ "//NameNode[@entry.cname = 'PyUnicode_Contains']")
+def unicode_contains_unbound(unicode s, substring):
+ """
+ >>> unicode_contains_unbound(text, 'fl')
+ True
+ >>> unicode_contains_unbound(text, 'XYZ')
+ False
+ >>> unicode_contains_unbound(None, 'XYZ') # doctest: +ELLIPSIS
+ Traceback (most recent call last):
+ TypeError: descriptor '__contains__' requires a '...' object but received a 'NoneType'
+ """
+ return unicode.__contains__(s, substring)
+
+
+cdef class UnicodeSubclass(unicode):
+ """
+ >>> u = UnicodeSubclass(text)
+ >>> 'fl' in u
+ False
+ >>> 'XYZ' in u
+ True
+ >>> u.method('fl')
+ False
+ >>> u.method('XYZ')
+ True
+ >>> u.operator('fl')
+ False
+ >>> u.operator('XYZ')
+ True
+ """
+ def __contains__(self, substring):
+ return substring not in (self + u'x')
+
+ def method(self, other):
+ return self.__contains__(other)
+
+ def operator(self, other):
+ return other in self