symbian-qemu-0.9.1-12/python-win32-2.6.1/lib/hotshot/log.py
changeset 1 2fb8b9db1c86
equal deleted inserted replaced
0:ffa851df0825 1:2fb8b9db1c86
       
     1 import _hotshot
       
     2 import os.path
       
     3 import parser
       
     4 import symbol
       
     5 
       
     6 from _hotshot import \
       
     7      WHAT_ENTER, \
       
     8      WHAT_EXIT, \
       
     9      WHAT_LINENO, \
       
    10      WHAT_DEFINE_FILE, \
       
    11      WHAT_DEFINE_FUNC, \
       
    12      WHAT_ADD_INFO
       
    13 
       
    14 
       
    15 __all__ = ["LogReader", "ENTER", "EXIT", "LINE"]
       
    16 
       
    17 
       
    18 ENTER = WHAT_ENTER
       
    19 EXIT  = WHAT_EXIT
       
    20 LINE  = WHAT_LINENO
       
    21 
       
    22 
       
    23 class LogReader:
       
    24     def __init__(self, logfn):
       
    25         # fileno -> filename
       
    26         self._filemap = {}
       
    27         # (fileno, lineno) -> filename, funcname
       
    28         self._funcmap = {}
       
    29 
       
    30         self._reader = _hotshot.logreader(logfn)
       
    31         self._nextitem = self._reader.next
       
    32         self._info = self._reader.info
       
    33         if self._info.has_key('current-directory'):
       
    34             self.cwd = self._info['current-directory']
       
    35         else:
       
    36             self.cwd = None
       
    37 
       
    38         # This mirrors the call stack of the profiled code as the log
       
    39         # is read back in.  It contains tuples of the form:
       
    40         #
       
    41         #   (file name, line number of function def, function name)
       
    42         #
       
    43         self._stack = []
       
    44         self._append = self._stack.append
       
    45         self._pop = self._stack.pop
       
    46 
       
    47     def close(self):
       
    48         self._reader.close()
       
    49 
       
    50     def fileno(self):
       
    51         """Return the file descriptor of the log reader's log file."""
       
    52         return self._reader.fileno()
       
    53 
       
    54     def addinfo(self, key, value):
       
    55         """This method is called for each additional ADD_INFO record.
       
    56 
       
    57         This can be overridden by applications that want to receive
       
    58         these events.  The default implementation does not need to be
       
    59         called by alternate implementations.
       
    60 
       
    61         The initial set of ADD_INFO records do not pass through this
       
    62         mechanism; this is only needed to receive notification when
       
    63         new values are added.  Subclasses can inspect self._info after
       
    64         calling LogReader.__init__().
       
    65         """
       
    66         pass
       
    67 
       
    68     def get_filename(self, fileno):
       
    69         try:
       
    70             return self._filemap[fileno]
       
    71         except KeyError:
       
    72             raise ValueError, "unknown fileno"
       
    73 
       
    74     def get_filenames(self):
       
    75         return self._filemap.values()
       
    76 
       
    77     def get_fileno(self, filename):
       
    78         filename = os.path.normcase(os.path.normpath(filename))
       
    79         for fileno, name in self._filemap.items():
       
    80             if name == filename:
       
    81                 return fileno
       
    82         raise ValueError, "unknown filename"
       
    83 
       
    84     def get_funcname(self, fileno, lineno):
       
    85         try:
       
    86             return self._funcmap[(fileno, lineno)]
       
    87         except KeyError:
       
    88             raise ValueError, "unknown function location"
       
    89 
       
    90     # Iteration support:
       
    91     # This adds an optional (& ignored) parameter to next() so that the
       
    92     # same bound method can be used as the __getitem__() method -- this
       
    93     # avoids using an additional method call which kills the performance.
       
    94 
       
    95     def next(self, index=0):
       
    96         while 1:
       
    97             # This call may raise StopIteration:
       
    98             what, tdelta, fileno, lineno = self._nextitem()
       
    99 
       
   100             # handle the most common cases first
       
   101 
       
   102             if what == WHAT_ENTER:
       
   103                 filename, funcname = self._decode_location(fileno, lineno)
       
   104                 t = (filename, lineno, funcname)
       
   105                 self._append(t)
       
   106                 return what, t, tdelta
       
   107 
       
   108             if what == WHAT_EXIT:
       
   109                 return what, self._pop(), tdelta
       
   110 
       
   111             if what == WHAT_LINENO:
       
   112                 filename, firstlineno, funcname = self._stack[-1]
       
   113                 return what, (filename, lineno, funcname), tdelta
       
   114 
       
   115             if what == WHAT_DEFINE_FILE:
       
   116                 filename = os.path.normcase(os.path.normpath(tdelta))
       
   117                 self._filemap[fileno] = filename
       
   118             elif what == WHAT_DEFINE_FUNC:
       
   119                 filename = self._filemap[fileno]
       
   120                 self._funcmap[(fileno, lineno)] = (filename, tdelta)
       
   121             elif what == WHAT_ADD_INFO:
       
   122                 # value already loaded into self.info; call the
       
   123                 # overridable addinfo() handler so higher-level code
       
   124                 # can pick up the new value
       
   125                 if tdelta == 'current-directory':
       
   126                     self.cwd = lineno
       
   127                 self.addinfo(tdelta, lineno)
       
   128             else:
       
   129                 raise ValueError, "unknown event type"
       
   130 
       
   131     def __iter__(self):
       
   132         return self
       
   133 
       
   134     #
       
   135     #  helpers
       
   136     #
       
   137 
       
   138     def _decode_location(self, fileno, lineno):
       
   139         try:
       
   140             return self._funcmap[(fileno, lineno)]
       
   141         except KeyError:
       
   142             #
       
   143             # This should only be needed when the log file does not
       
   144             # contain all the DEFINE_FUNC records needed to allow the
       
   145             # function name to be retrieved from the log file.
       
   146             #
       
   147             if self._loadfile(fileno):
       
   148                 filename = funcname = None
       
   149             try:
       
   150                 filename, funcname = self._funcmap[(fileno, lineno)]
       
   151             except KeyError:
       
   152                 filename = self._filemap.get(fileno)
       
   153                 funcname = None
       
   154                 self._funcmap[(fileno, lineno)] = (filename, funcname)
       
   155         return filename, funcname
       
   156 
       
   157     def _loadfile(self, fileno):
       
   158         try:
       
   159             filename = self._filemap[fileno]
       
   160         except KeyError:
       
   161             print "Could not identify fileId", fileno
       
   162             return 1
       
   163         if filename is None:
       
   164             return 1
       
   165         absname = os.path.normcase(os.path.join(self.cwd, filename))
       
   166 
       
   167         try:
       
   168             fp = open(absname)
       
   169         except IOError:
       
   170             return
       
   171         st = parser.suite(fp.read())
       
   172         fp.close()
       
   173 
       
   174         # Scan the tree looking for def and lambda nodes, filling in
       
   175         # self._funcmap with all the available information.
       
   176         funcdef = symbol.funcdef
       
   177         lambdef = symbol.lambdef
       
   178 
       
   179         stack = [st.totuple(1)]
       
   180 
       
   181         while stack:
       
   182             tree = stack.pop()
       
   183             try:
       
   184                 sym = tree[0]
       
   185             except (IndexError, TypeError):
       
   186                 continue
       
   187             if sym == funcdef:
       
   188                 self._funcmap[(fileno, tree[2][2])] = filename, tree[2][1]
       
   189             elif sym == lambdef:
       
   190                 self._funcmap[(fileno, tree[1][2])] = filename, "<lambda>"
       
   191             stack.extend(list(tree[1:]))