Debug.py
上传用户:market2
上传日期:2018-11-18
资源大小:18786k
文件大小:6k
源码类别:

外挂编程

开发平台:

Windows_Unix

  1. """SCons.Debug
  2. Code for debugging SCons internal things.  Not everything here is
  3. guaranteed to work all the way back to Python 1.5.2, and shouldn't be
  4. needed by most users.
  5. """
  6. #
  7. # Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 The SCons Foundation
  8. #
  9. # Permission is hereby granted, free of charge, to any person obtaining
  10. # a copy of this software and associated documentation files (the
  11. # "Software"), to deal in the Software without restriction, including
  12. # without limitation the rights to use, copy, modify, merge, publish,
  13. # distribute, sublicense, and/or sell copies of the Software, and to
  14. # permit persons to whom the Software is furnished to do so, subject to
  15. # the following conditions:
  16. #
  17. # The above copyright notice and this permission notice shall be included
  18. # in all copies or substantial portions of the Software.
  19. #
  20. # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY
  21. # KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
  22. # WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  23. # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
  24. # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  25. # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  26. # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  27. #
  28. __revision__ = "src/engine/SCons/Debug.py 3057 2008/06/09 22:21:00 knight"
  29. import os
  30. import string
  31. import sys
  32. # Recipe 14.10 from the Python Cookbook.
  33. try:
  34.     import weakref
  35. except ImportError:
  36.     def logInstanceCreation(instance, name=None):
  37.         pass
  38. else:
  39.     def logInstanceCreation(instance, name=None):
  40.         if name is None:
  41.             name = instance.__class__.__name__
  42.         if not tracked_classes.has_key(name):
  43.             tracked_classes[name] = []
  44.         tracked_classes[name].append(weakref.ref(instance))
  45. tracked_classes = {}
  46. def string_to_classes(s):
  47.     if s == '*':
  48.         c = tracked_classes.keys()
  49.         c.sort()
  50.         return c
  51.     else:
  52.         return string.split(s)
  53. def fetchLoggedInstances(classes="*"):
  54.     classnames = string_to_classes(classes)
  55.     return map(lambda cn: (cn, len(tracked_classes[cn])), classnames)
  56.   
  57. def countLoggedInstances(classes, file=sys.stdout):
  58.     for classname in string_to_classes(classes):
  59.         file.write("%s: %dn" % (classname, len(tracked_classes[classname])))
  60. def listLoggedInstances(classes, file=sys.stdout):
  61.     for classname in string_to_classes(classes):
  62.         file.write('n%s:n' % classname)
  63.         for ref in tracked_classes[classname]:
  64.             obj = ref()
  65.             if obj is not None:
  66.                 file.write('    %sn' % repr(obj))
  67. def dumpLoggedInstances(classes, file=sys.stdout):
  68.     for classname in string_to_classes(classes):
  69.         file.write('n%s:n' % classname)
  70.         for ref in tracked_classes[classname]:
  71.             obj = ref()
  72.             if obj is not None:
  73.                 file.write('    %s:n' % obj)
  74.                 for key, value in obj.__dict__.items():
  75.                     file.write('        %20s : %sn' % (key, value))
  76. if sys.platform[:5] == "linux":
  77.     # Linux doesn't actually support memory usage stats from getrusage().
  78.     def memory():
  79.         mstr = open('/proc/self/stat').read()
  80.         mstr = string.split(mstr)[22]
  81.         return int(mstr)
  82. else:
  83.     try:
  84.         import resource
  85.     except ImportError:
  86.         try:
  87.             import win32process
  88.             import win32api
  89.         except ImportError:
  90.             def memory():
  91.                 return 0
  92.         else:
  93.             def memory():
  94.                 process_handle = win32api.GetCurrentProcess()
  95.                 memory_info = win32process.GetProcessMemoryInfo( process_handle )
  96.                 return memory_info['PeakWorkingSetSize']
  97.     else:
  98.         def memory():
  99.             res = resource.getrusage(resource.RUSAGE_SELF)
  100.             return res[4]
  101. # returns caller's stack
  102. def caller_stack(*backlist):
  103.     import traceback
  104.     if not backlist:
  105.         backlist = [0]
  106.     result = []
  107.     for back in backlist:
  108.         tb = traceback.extract_stack(limit=3+back)
  109.         key = tb[0][:3]
  110.         result.append('%s:%d(%s)' % func_shorten(key))
  111.     return result
  112. caller_bases = {}
  113. caller_dicts = {}
  114. # trace a caller's stack
  115. def caller_trace(back=0):
  116.     import traceback
  117.     tb = traceback.extract_stack(limit=3+back)
  118.     tb.reverse()
  119.     callee = tb[1][:3]
  120.     caller_bases[callee] = caller_bases.get(callee, 0) + 1
  121.     for caller in tb[2:]:
  122.         caller = callee + caller[:3]
  123.         try:
  124.             entry = caller_dicts[callee]
  125.         except KeyError:
  126.             caller_dicts[callee] = entry = {}
  127.         entry[caller] = entry.get(caller, 0) + 1
  128.         callee = caller
  129. # print a single caller and its callers, if any
  130. def _dump_one_caller(key, file, level=0):
  131.     l = []
  132.     for c,v in caller_dicts[key].items():
  133.         l.append((-v,c))
  134.     l.sort()
  135.     leader = '      '*level
  136.     for v,c in l:
  137.         file.write("%s  %6d %s:%d(%s)n" % ((leader,-v) + func_shorten(c[-3:])))
  138.         if caller_dicts.has_key(c):
  139.             _dump_one_caller(c, file, level+1)
  140. # print each call tree
  141. def dump_caller_counts(file=sys.stdout):
  142.     keys = caller_bases.keys()
  143.     keys.sort()
  144.     for k in keys:
  145.         file.write("Callers of %s:%d(%s), %d calls:n"
  146.                     % (func_shorten(k) + (caller_bases[k],)))
  147.         _dump_one_caller(k, file)
  148. shorten_list = [
  149.     ( '/scons/SCons/',          1),
  150.     ( '/src/engine/SCons/',     1),
  151.     ( '/usr/lib/python',        0),
  152. ]
  153. if os.sep != '/':
  154.    def platformize(t):
  155.        return (string.replace(t[0], '/', os.sep), t[1])
  156.    shorten_list = map(platformize, shorten_list)
  157.    del platformize
  158. def func_shorten(func_tuple):
  159.     f = func_tuple[0]
  160.     for t in shorten_list:
  161.         i = string.find(f, t[0])
  162.         if i >= 0:
  163.             if t[1]:
  164.                 i = i + len(t[0])
  165.             return (f[i:],)+func_tuple[1:]
  166.     return func_tuple
  167. TraceFP = {}
  168. if sys.platform == 'win32':
  169.     TraceDefault = 'con'
  170. else:
  171.     TraceDefault = '/dev/tty'
  172. def Trace(msg, file=None, mode='w'):
  173.     """Write a trace message to a file.  Whenever a file is specified,
  174.     it becomes the default for the next call to Trace()."""
  175.     global TraceDefault
  176.     if file is None:
  177.         file = TraceDefault
  178.     else:
  179.         TraceDefault = file
  180.     try:
  181.         fp = TraceFP[file]
  182.     except KeyError:
  183.         try:
  184.             fp = TraceFP[file] = open(file, mode)
  185.         except TypeError:
  186.             # Assume we were passed an open file pointer.
  187.             fp = file
  188.     fp.write(msg)
  189.     fp.flush()