diff options
Diffstat (limited to 'Lib/hotshot/log.py')
-rw-r--r-- | Lib/hotshot/log.py | 192 |
1 files changed, 0 insertions, 192 deletions
diff --git a/Lib/hotshot/log.py b/Lib/hotshot/log.py deleted file mode 100644 index b211825..0000000 --- a/Lib/hotshot/log.py +++ /dev/null @@ -1,192 +0,0 @@ -import _hotshot -import os.path -import parser -import symbol -import sys - -from _hotshot import \ - WHAT_ENTER, \ - WHAT_EXIT, \ - WHAT_LINENO, \ - WHAT_DEFINE_FILE, \ - WHAT_DEFINE_FUNC, \ - WHAT_ADD_INFO - - -__all__ = ["LogReader", "ENTER", "EXIT", "LINE"] - - -ENTER = WHAT_ENTER -EXIT = WHAT_EXIT -LINE = WHAT_LINENO - - -class LogReader: - def __init__(self, logfn): - # fileno -> filename - self._filemap = {} - # (fileno, lineno) -> filename, funcname - self._funcmap = {} - - self._reader = _hotshot.logreader(logfn) - self._nextitem = self._reader.__next__ - self._info = self._reader.info - if 'current-directory' in self._info: - self.cwd = self._info['current-directory'] - else: - self.cwd = None - - # This mirrors the call stack of the profiled code as the log - # is read back in. It contains tuples of the form: - # - # (file name, line number of function def, function name) - # - self._stack = [] - self._append = self._stack.append - self._pop = self._stack.pop - - def close(self): - self._reader.close() - - def fileno(self): - """Return the file descriptor of the log reader's log file.""" - return self._reader.fileno() - - def addinfo(self, key, value): - """This method is called for each additional ADD_INFO record. - - This can be overridden by applications that want to receive - these events. The default implementation does not need to be - called by alternate implementations. - - The initial set of ADD_INFO records do not pass through this - mechanism; this is only needed to receive notification when - new values are added. Subclasses can inspect self._info after - calling LogReader.__init__(). - """ - pass - - def get_filename(self, fileno): - try: - return self._filemap[fileno] - except KeyError: - raise ValueError("unknown fileno") - - def get_filenames(self): - return self._filemap.values() - - def get_fileno(self, filename): - filename = os.path.normcase(os.path.normpath(filename)) - for fileno, name in self._filemap.items(): - if name == filename: - return fileno - raise ValueError("unknown filename") - - def get_funcname(self, fileno, lineno): - try: - return self._funcmap[(fileno, lineno)] - except KeyError: - raise ValueError("unknown function location") - - # Iteration support: - # This adds an optional (& ignored) parameter to next() so that the - # same bound method can be used as the __getitem__() method -- this - # avoids using an additional method call which kills the performance. - - def __next__(self, index=0): - while 1: - # This call may raise StopIteration: - what, tdelta, fileno, lineno = self._nextitem() - - # handle the most common cases first - - if what == WHAT_ENTER: - filename, funcname = self._decode_location(fileno, lineno) - t = (filename, lineno, funcname) - self._append(t) - return what, t, tdelta - - if what == WHAT_EXIT: - return what, self._pop(), tdelta - - if what == WHAT_LINENO: - filename, firstlineno, funcname = self._stack[-1] - return what, (filename, lineno, funcname), tdelta - - if what == WHAT_DEFINE_FILE: - filename = os.path.normcase(os.path.normpath(tdelta)) - self._filemap[fileno] = filename - elif what == WHAT_DEFINE_FUNC: - filename = self._filemap[fileno] - self._funcmap[(fileno, lineno)] = (filename, tdelta) - elif what == WHAT_ADD_INFO: - # value already loaded into self.info; call the - # overridable addinfo() handler so higher-level code - # can pick up the new value - if tdelta == 'current-directory': - self.cwd = lineno - self.addinfo(tdelta, lineno) - else: - raise ValueError("unknown event type") - - def __iter__(self): - return self - - # - # helpers - # - - def _decode_location(self, fileno, lineno): - try: - return self._funcmap[(fileno, lineno)] - except KeyError: - # - # This should only be needed when the log file does not - # contain all the DEFINE_FUNC records needed to allow the - # function name to be retrieved from the log file. - # - if self._loadfile(fileno): - filename = funcname = None - try: - filename, funcname = self._funcmap[(fileno, lineno)] - except KeyError: - filename = self._filemap.get(fileno) - funcname = None - self._funcmap[(fileno, lineno)] = (filename, funcname) - return filename, funcname - - def _loadfile(self, fileno): - try: - filename = self._filemap[fileno] - except KeyError: - print("Could not identify fileId", fileno) - return 1 - if filename is None: - return 1 - absname = os.path.normcase(os.path.join(self.cwd, filename)) - - try: - fp = open(absname) - except IOError: - return - st = parser.suite(fp.read()) - fp.close() - - # Scan the tree looking for def and lambda nodes, filling in - # self._funcmap with all the available information. - funcdef = symbol.funcdef - lambdef = symbol.lambdef - - stack = [st.totuple(1)] - - while stack: - tree = stack.pop() - try: - sym = tree[0] - except (IndexError, TypeError): - continue - if sym == funcdef: - self._funcmap[(fileno, tree[2][2])] = filename, tree[2][1] - elif sym == lambdef: - self._funcmap[(fileno, tree[1][2])] = filename, "<lambda>" - stack.extend(list(tree[1:])) |