From a40112b0461eae5ab22fbdd07ae798d4a72ff523 Mon Sep 17 00:00:00 2001
From: Stefan Behnel <stefan_ml@behnel.de>
Date: Wed, 25 Apr 2012 12:44:43 +0200
Subject: [PATCH] optimise built-in callable() function

---
 Cython/Compiler/Builtin.py      |  2 ++
 Cython/Utility/ObjectHandling.c |  8 ++++++++
 tests/run/builtin_callable.pyx  | 19 +++++++++++++++++++
 3 files changed, 29 insertions(+)
 create mode 100644 tests/run/builtin_callable.pyx

diff --git a/Cython/Compiler/Builtin.py b/Cython/Compiler/Builtin.py
index 7435180f8..b2af5ede2 100644
--- a/Cython/Compiler/Builtin.py
+++ b/Cython/Compiler/Builtin.py
@@ -333,6 +333,8 @@ builtin_function_table = [
                             ],
                         is_strict_signature = True)),
     BuiltinFunction('abs',        "O",    "O",     "PyNumber_Absolute"),
+    BuiltinFunction('callable',   "O",    "b",     "__Pyx_PyCallable_Check",
+                    utility_code = UtilityCode.load_cached("CallableCheck", "ObjectHandling.c")),
     #('chr',       "",     "",      ""),
     #('cmp', "",   "",     "",      ""), # int PyObject_Cmp(PyObject *o1, PyObject *o2, int *result)
     #('compile',   "",     "",      ""), # PyObject* Py_CompileString(    char *str, char *filename, int start)
diff --git a/Cython/Utility/ObjectHandling.c b/Cython/Utility/ObjectHandling.c
index 076a531c5..213d4836d 100644
--- a/Cython/Utility/ObjectHandling.c
+++ b/Cython/Utility/ObjectHandling.c
@@ -432,3 +432,11 @@ static CYTHON_INLINE int __Pyx_TypeTest(PyObject *obj, PyTypeObject *type) {
                  Py_TYPE(obj)->tp_name, type->tp_name);
     return 0;
 }
+
+/////////////// CallableCheck.proto ///////////////
+
+#if CYTHON_COMPILING_IN_CPYTHON
+#define __Pyx_PyCallable_Check(obj)   ((obj)->ob_type->tp_call != NULL)
+#else
+#define __Pyx_PyCallable_Check(obj)   PyCallable_Check(obj)
+#endif
diff --git a/tests/run/builtin_callable.pyx b/tests/run/builtin_callable.pyx
new file mode 100644
index 000000000..6427e4f21
--- /dev/null
+++ b/tests/run/builtin_callable.pyx
@@ -0,0 +1,19 @@
+# mode: run
+# tag: builtin, callable
+
+cimport cython
+
+@cython.test_assert_path_exists("//SimpleCallNode[@type.is_pyobject = False]")
+def test_callable(x):
+    """
+    >>> test_callable(None)
+    False
+    >>> test_callable('ABC')
+    False
+    >>> test_callable(int)
+    True
+    >>> test_callable(test_callable)
+    True
+    """
+    b = callable(x)
+    return b
-- 
GitLab