Added the cProfile module.
Based on lsprof (patch #1212837) by Brett Rosen and Ted Czotter.
With further editing by Michael Hudson and myself.
History in svn repo: http://codespeak.net/svn/user/arigo/hack/misc/lsprof

* Module/_lsprof.c is the internal C module, Lib/cProfile.py a wrapper.
* pstats.py updated to display cProfile's caller/callee timings if available.
* setup.py and NEWS updated.
* documentation updates in the profiler section:
   - explain the differences between the three profilers that we have now
   - profile and cProfile can use a unified documentation, like (c)Pickle
   - mention that hotshot is "for specialized usage" now
   - removed references to the "old profiler" that no longer exists
* test updates:
   - extended test_profile to cover delicate cases like recursion
   - added tests for the caller/callee displays
   - added test_cProfile, performing the same tests for cProfile
* TO-DO:
   - cProfile gives a nicer name to built-in, particularly built-in methods,
     which could be backported to profile.
   - not tested on Windows recently!
diff --git a/Lib/pstats.py b/Lib/pstats.py
index 98f351f..930cc6d 100644
--- a/Lib/pstats.py
+++ b/Lib/pstats.py
@@ -371,27 +371,47 @@
             self.print_call_heading(width, "was called by...")
             for func in list:
                 cc, nc, tt, ct, callers = self.stats[func]
-                self.print_call_line(width, func, callers)
+                self.print_call_line(width, func, callers, "<-")
             print
             print
         return self
 
     def print_call_heading(self, name_size, column_title):
         print "Function ".ljust(name_size) + column_title
+        # print sub-header only if we have new-style callers
+        subheader = False
+        for cc, nc, tt, ct, callers in self.stats.itervalues():
+            if callers:
+                value = callers.itervalues().next()
+                subheader = isinstance(value, tuple)
+                break
+        if subheader:
+            print " "*name_size + "    ncalls  tottime  cumtime"
 
-    def print_call_line(self, name_size, source, call_dict):
-        print func_std_string(source).ljust(name_size),
+    def print_call_line(self, name_size, source, call_dict, arrow="->"):
+        print func_std_string(source).ljust(name_size) + arrow,
         if not call_dict:
-            print "--"
+            print
             return
         clist = call_dict.keys()
         clist.sort()
-        name_size = name_size + 1
         indent = ""
         for func in clist:
             name = func_std_string(func)
-            print indent*name_size + name + '(%r)' % (call_dict[func],), \
-                      f8(self.stats[func][3])
+            value = call_dict[func]
+            if isinstance(value, tuple):
+                nc, cc, tt, ct = value
+                if nc != cc:
+                    substats = '%d/%d' % (nc, cc)
+                else:
+                    substats = '%d' % (nc,)
+                substats = '%s %s %s  %s' % (substats.rjust(7+2*len(indent)),
+                                             f8(tt), f8(ct), name)
+                left_width = name_size + 1
+            else:
+                substats = '%s(%r) %s' % (name, value, f8(self.stats[func][3]))
+                left_width = name_size + 3
+            print indent*left_width + substats
             indent = " "
 
     def print_title(self):
@@ -448,7 +468,15 @@
     return func[2]
 
 def func_std_string(func_name): # match what old profile produced
-    return "%s:%d(%s)" % func_name
+    if func_name[:2] == ('~', 0):
+        # special case for built-in functions
+        name = func_name[2]
+        if name.startswith('<') and name.endswith('>'):
+            return '{%s}' % name[1:-1]
+        else:
+            return name
+    else:
+        return "%s:%d(%s)" % func_name
 
 #**************************************************************************
 # The following functions combine statists for pairs functions.