]> granicus.if.org Git - python/commitdiff
Issue #5330: C functions called with keyword arguments were not reported by
authorAntoine Pitrou <solipsis@pitrou.net>
Sat, 30 May 2009 21:27:00 +0000 (21:27 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Sat, 30 May 2009 21:27:00 +0000 (21:27 +0000)
the various profiling modules (profile, cProfile). Patch by Hagen Fürstenau.

Lib/test/test_cprofile.py
Lib/test/test_profile.py
Misc/NEWS
Python/ceval.c

index 13c1060118e5708cc716e1581dacd87cc397d880..831895c389fd04fffdf3b9e416a8eaca03375b2a 100755 (executable)
@@ -9,6 +9,7 @@ from test.test_profile import ProfileTest, regenerate_expected_output
 
 class CProfileTest(ProfileTest):
     profilerclass = cProfile.Profile
+    expected_list_sort_output = "{method 'sort' of 'list' objects}"
 
     # Issue 3895.
     def test_bad_counter_during_dealloc(self):
index 0bd2530cf2abf5dd847716960e370ff3364f091f..421aa1b40426e8c9aa93db29ff16f06b535962de 100755 (executable)
@@ -16,6 +16,7 @@ class ProfileTest(unittest.TestCase):
     profilerclass = profile.Profile
     methodnames = ['print_stats', 'print_callers', 'print_callees']
     expected_output = {}
+    expected_list_sort_output = ':0(sort)'
 
     @classmethod
     def do_profiling(cls):
@@ -40,6 +41,25 @@ class ProfileTest(unittest.TestCase):
                              "Stats.%s output for %s doesn't fit expectation!" %
                              (method, self.profilerclass.__name__))
 
+    def test_calling_conventions(self):
+        # Issue #5330: profile and cProfile wouldn't report C functions called
+        # with keyword arguments. We test all calling conventions.
+        prof = self.profilerclass(timer, 0.001)
+        stmts = [
+            "[].sort()",
+            "[].sort(reverse=True)",
+            "[].sort(*(None, None, True))",
+            "[].sort(**dict(reverse=True))",
+        ]
+        for stmt in stmts:
+            s = StringIO()
+            prof.runctx(stmt, globals(), locals())
+            stats = pstats.Stats(prof, stream=s)
+            stats.print_stats()
+            res = s.getvalue()
+            self.assertTrue(self.expected_list_sort_output in res,
+                "Profiling {0!r} didn't report list.sort:\n{1}".format(stmt, res))
+
 
 def regenerate_expected_output(filename, cls):
     filename = filename.rstrip('co')
index 73ddbe73f6d12d54207ba509438557cfadc43c0d..6eb1c34314a0b69151d88b8db53f8ba86cf23bf4 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 2.7 alpha 1
 Core and Builtins
 -----------------
 
+- Issue #5330: C functions called with keyword arguments were not reported by
+  the various profiling modules (profile, cProfile). Patch by Hagen Fürstenau.
+
 - Issue #5982: staticmethod and classmethod now expose the wrapped
   function with __func__.
 
index 92021e651a91a75922742bc661ca92c30151c6e3..dd91f5d0dc30325f791415340cca58658955e922 100644 (file)
@@ -4160,10 +4160,17 @@ do_call(PyObject *func, PyObject ***pp_stack, int na, int nk)
                PCALL(PCALL_METHOD);
        else if (PyType_Check(func))
                PCALL(PCALL_TYPE);
+       else if (PyCFunction_Check(func))
+               PCALL(PCALL_CFUNCTION);
        else
                PCALL(PCALL_OTHER);
 #endif
-       result = PyObject_Call(func, callargs, kwdict);
+       if (PyCFunction_Check(func)) {
+               PyThreadState *tstate = PyThreadState_GET();
+               C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
+       }
+       else
+               result = PyObject_Call(func, callargs, kwdict);
  call_fail:
        Py_XDECREF(callargs);
        Py_XDECREF(kwdict);
@@ -4248,10 +4255,17 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
                PCALL(PCALL_METHOD);
        else if (PyType_Check(func))
                PCALL(PCALL_TYPE);
+       else if (PyCFunction_Check(func))
+               PCALL(PCALL_CFUNCTION);
        else
                PCALL(PCALL_OTHER);
 #endif
-       result = PyObject_Call(func, callargs, kwdict);
+       if (PyCFunction_Check(func)) {
+               PyThreadState *tstate = PyThreadState_GET();
+               C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
+       }
+       else
+               result = PyObject_Call(func, callargs, kwdict);
 ext_call_fail:
        Py_XDECREF(callargs);
        Py_XDECREF(kwdict);