]> granicus.if.org Git - python/commitdiff
Merged revisions 73064 via svnmerge from
authorAntoine Pitrou <solipsis@pitrou.net>
Sat, 30 May 2009 21:41:10 +0000 (21:41 +0000)
committerAntoine Pitrou <solipsis@pitrou.net>
Sat, 30 May 2009 21:41:10 +0000 (21:41 +0000)
svn+ssh://pythondev@svn.python.org/python/trunk

........
  r73064 | antoine.pitrou | 2009-05-30 23:27:00 +0200 (sam., 30 mai 2009) | 4 lines

  Issue #5330: C functions called with keyword arguments were not reported by
  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 349d342665eb1f66b92c35175545bae042cfda77..4586b36deb25b3d79578780f58029fd36793a310 100644 (file)
@@ -9,6 +9,7 @@ from test.test_profile import ProfileTest, regenerate_expected_output
 
 class CProfileTest(ProfileTest):
     profilerclass = cProfile.Profile
+    expected_max_output = "{built-in method max}"
 
     def get_expected_output(self):
         return _ProfileOutput
index c972fc6f62908f0458e74a2f3c9706519762e942..243a322582ae2a0705e11164b8a71c758d1f09fd 100755 (executable)
@@ -16,6 +16,7 @@ class ProfileTest(unittest.TestCase):
 
     profilerclass = profile.Profile
     methodnames = ['print_stats', 'print_callers', 'print_callees']
+    expected_max_output = ':0(max)'
 
     def get_expected_output(self):
         return _ProfileOutput
@@ -53,6 +54,27 @@ class ProfileTest(unittest.TestCase):
                                   results[i+1].split('\n'),
                                   expected[method].split('\n'))))
 
+    def test_calling_conventions(self):
+        # Issue #5330: profile and cProfile wouldn't report C functions called
+        # with keyword arguments. We test all calling conventions.
+        stmts = [
+            "max([0])",
+            "max([0], key=int)",
+            "max([0], **dict(key=int))",
+            "max(*([0],))",
+            "max(*([0],), key=int)",
+            "max(*([0],), **dict(key=int))",
+        ]
+        for stmt in stmts:
+            s = StringIO()
+            prof = self.profilerclass(timer, 0.001)
+            prof.runctx(stmt, globals(), locals())
+            stats = pstats.Stats(prof, stream=s)
+            stats.print_stats()
+            res = s.getvalue()
+            self.assertTrue(self.expected_max_output in res,
+                "Profiling {0!r} didn't report max:\n{1}".format(stmt, res))
+
 
 def regenerate_expected_output(filename, cls):
     filename = filename.rstrip('co')
index 6fa6d99a6fb4eca31f88040697c41620aaa39c07..b06767d0717bcd53e55a74f07708b782b52d3848 100644 (file)
--- a/Misc/NEWS
+++ b/Misc/NEWS
@@ -12,6 +12,9 @@ What's New in Python 3.1 Release Candidate 2?
 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.
+
 Library
 -------
 
index e693147c2a7e380d296b1cf0eabfccfab6a85988..b5b5c272721a9c446bebeff5ffd18f9315ca8d41 100644 (file)
@@ -3951,10 +3951,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);
@@ -4039,10 +4046,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);