diff -r e9e7eca7efee -r bf71ee032bb4 src/eric7/DebugClients/Python/PyProfile.py --- a/src/eric7/DebugClients/Python/PyProfile.py Wed Jul 13 11:16:20 2022 +0200 +++ b/src/eric7/DebugClients/Python/PyProfile.py Wed Jul 13 14:55:47 2022 +0200 @@ -10,23 +10,24 @@ import marshal import profile import atexit -import pickle # secok +import pickle # secok import contextlib class PyProfile(profile.Profile): """ Class extending the standard Python profiler with additional methods. - + This class extends the standard Python profiler by the functionality to save the collected timing data in a timing cache, to restore these data on subsequent calls, to store a profile dump to a standard filename and to erase these caches. """ + def __init__(self, basename, timer=None, bias=None): """ Constructor - + @param basename name of the script to be profiled (string) @param timer function defining the timing calculation @param bias calibration value (float) @@ -35,50 +36,49 @@ profile.Profile.__init__(self, timer, bias) except TypeError: profile.Profile.__init__(self, timer) - + self.dispatch = self.__class__.dispatch - + basename = os.path.splitext(basename)[0] self.profileCache = "{0}.profile".format(basename) self.timingCache = "{0}.timings".format(basename) - + self.__restore() atexit.register(self.save) - + def __restore(self): """ Private method to restore the timing data from the timing cache. """ if not os.path.exists(self.timingCache): return - - with contextlib.suppress(OSError, EOFError, ValueError, TypeError), \ - open(self.timingCache, 'rb') as cache: - timings = marshal.load(cache) # secok + + with contextlib.suppress(OSError, EOFError, ValueError, TypeError), open( + self.timingCache, "rb" + ) as cache: + timings = marshal.load(cache) # secok if isinstance(timings, dict): self.timings = timings - + def save(self): """ Public method to store the collected profile data. """ # dump the raw timing data - with contextlib.suppress(OSError), \ - open(self.timingCache, 'wb') as cache: + with contextlib.suppress(OSError), open(self.timingCache, "wb") as cache: marshal.dump(self.timings, cache) - + # dump the profile data self.dump_stats(self.profileCache) - + def dump_stats(self, file): """ Public method to dump the statistics data. - + @param file name of the file to write to (string) """ self.create_stats() - with contextlib.suppress(OSError, pickle.PickleError), \ - open(file, 'wb') as f: + with contextlib.suppress(OSError, pickle.PickleError), open(file, "wb") as f: pickle.dump(self.stats, f, 4) def erase(self): @@ -92,7 +92,7 @@ def fix_frame_filename(self, frame): """ Public method used to fixup the filename for a given frame. - + The logic employed here is that if a module was loaded from a .pyc file, then the correct .py to operate with should be in the same path as the .pyc. The reason this @@ -103,21 +103,23 @@ this can break debugging as the .pyc will refer to the .py on the original machine. Another case might be sharing code over a network... This logic deals with that. - + @param frame the frame object @return fixed up file name (string) """ - versionExt = '.py3' - + versionExt = ".py3" + # get module name from __file__ - if (not isinstance(frame, profile.Profile.fake_frame) and - '__file__' in frame.f_globals): - root, ext = os.path.splitext(frame.f_globals['__file__']) - if ext in ['.pyc', '.py', versionExt, '.pyo']: - fixedName = root + '.py' + if ( + not isinstance(frame, profile.Profile.fake_frame) + and "__file__" in frame.f_globals + ): + root, ext = os.path.splitext(frame.f_globals["__file__"]) + if ext in [".pyc", ".py", versionExt, ".pyo"]: + fixedName = root + ".py" if os.path.exists(fixedName): return fixedName - + fixedName = root + versionExt if os.path.exists(fixedName): return fixedName @@ -127,10 +129,10 @@ def trace_dispatch_call(self, frame, t): """ Public method used to trace functions calls. - + This is a variant of the one found in the standard Python profile.py calling fix_frame_filename above. - + @param frame reference to the call frame @param t arguments @return flag indicating a successful handling (boolean) @@ -138,16 +140,21 @@ if self.cur and frame.f_back is not self.cur[-2]: rpt, rit, ret, rfn, rframe, rcur = self.cur if not isinstance(rframe, profile.Profile.fake_frame): - assert rframe.f_back is frame.f_back, ( # secok - "Bad call", rfn, rframe, rframe.f_back, - frame, frame.f_back) + assert rframe.f_back is frame.f_back, ( # secok + "Bad call", + rfn, + rframe, + rframe.f_back, + frame, + frame.f_back, + ) self.trace_dispatch_return(rframe, 0) - assert (self.cur is None or # secok - frame.f_back is self.cur[-2]), ("Bad call", - self.cur[-3]) + assert self.cur is None or frame.f_back is self.cur[-2], ( # secok + "Bad call", + self.cur[-3], + ) fcode = frame.f_code - fn = (self.fix_frame_filename(frame), - fcode.co_firstlineno, fcode.co_name) + fn = (self.fix_frame_filename(frame), fcode.co_firstlineno, fcode.co_name) self.cur = (t, 0, 0, fn, frame, self.cur) timings = self.timings if fn in timings: @@ -156,7 +163,7 @@ else: timings[fn] = 0, 0, 0, 0, {} return 1 - + dispatch = { "call": trace_dispatch_call, "exception": profile.Profile.trace_dispatch_exception,