X7ROOT File Manager
Current Path:
/opt/cloudlinux/venv/lib/python3.11/site-packages/guppy/heapy
opt
/
cloudlinux
/
venv
/
lib
/
python3.11
/
site-packages
/
guppy
/
heapy
/
??
..
??
Classifiers.py
(45.16 KB)
??
Console.py
(843 B)
??
Doc.py
(7.81 KB)
??
ImpSet.py
(870 B)
??
Monitor.py
(14.5 KB)
??
OutputHandling.py
(11.52 KB)
??
Part.py
(23.25 KB)
??
Path.py
(14.19 KB)
??
Prof.py
(90.38 KB)
??
RM.py
(119 B)
??
RefPat.py
(18.18 KB)
??
Remote.py
(15.31 KB)
??
RemoteConstants.py
(209 B)
??
Spec.py
(48.59 KB)
??
Target.py
(205 B)
??
UniSet.py
(66.5 KB)
??
Use.py
(23.05 KB)
??
View.py
(19.05 KB)
??
__init__.py
(209 B)
??
__pycache__
??
heapyc.cpython-311-x86_64-linux-gnu.so
(154.55 KB)
??
pbhelp.py
(17.4 KB)
??
test
Editing: Prof.py
from tkinter import * import tkinter.filedialog import tkinter.messagebox from guppy.etc.Descriptor import property_nondata class MyVar(StringVar): _default = 0.0 def set(self, value): StringVar.set(self, '%.2g' % value) suffixes = ('', 'K', 'M', 'G', 'T') def sizestring(value): value = float(value) sign = 1 if value < 0: sign = -1 value = - value i = 0 while value > 99999: value /= 1000 i += 1 s = str(int(round(value)))+suffixes[i] if s.endswith('000'+suffixes[i]): s = str(int(round(value/1000)))+suffixes[i+1] if sign == -1: s = '-' + s return s def percentstring(value): a = abs(value) if 10 <= a <= 9999: return '%d' % round(value) elif 0.01 <= a <= 10: return '%.2g' % value elif a <= 1e-10: return '0' else: return '%.0e' % value def stringsize(s): if s.isdigit(): return int(s) suf = s[-1:].upper() mult = 1000 for su in suffixes[1:]: if su == suf: break mult *= 1000 else: raise ValueError return int(s[:-1])*mult class Menu(Menu): # A fix for the .delete() method in Menu. # To delete commands defined in the menu items deleted. # Also changed the comment: INDEX2 is actually INCLUDED. def delete(self, index1, index2=None): """Delete menu items between INDEX1 and INDEX2 (included).""" if index2 is None: index2 = index1 # First find out what entries have defined commands. cmds = [] for i in range(self.index(index1), self.index(index2)+1): c = str(self.entrycget(i, 'command')) if c in self._tclCommands: # I don't want to delete the command already, since it # seems mystical to do that while the entry is not yet deleted. cmds.append(c) # Delete the menu entries. self.tk.call(self._w, 'delete', index1, index2) # Now that the menu entries have been deleted, # we can delete their commands. for c in cmds: self.deletecommand(c) class SizeVar(StringVar): _default = 0.0 def set(self, value): self._value = value s = sizestring(value) StringVar.set(self, s) class ValueLabel(Label): def __init__(self, *args, **kwds): kwds['width'] = 10 Label.__init__(self, *args, **kwds) class ClickButton(Button): # Button that runs the command directly at the click, not at release. # And has auto-repeat. def __init__(self, master, command, firstdelay=500, thendelay=150, **kwds): Button.__init__(self, master, **kwds) self._command = command self._firstdelay = firstdelay self._thendelay = thendelay self.bind('<Button-1>', self._event_button) self.bind('<ButtonRelease-1>', self._event_release) def _event_button(self, event=None): self._command() if event is not None: delay = self._firstdelay else: delay = self._thendelay self._after = self.after(delay, self._event_button) def _event_release(self, event): self.after_cancel(self._after) del self._after class Stats: def __init__(self, mod, fn=None): self.mod = mod self.os = mod.os self.hashlib = mod.hashlib self.fn = fn def clear_cache(self): # It is intended to be transparently # automagically reopened when needed. self.stats = None del self.stats def get_stats(self): self.open(self.fn) return self.stats stats = property_nondata(get_stats) def collect(self): if not self.fn: return 0, 0 stat = self.os.stat(self.fn) if stat == self.laststat: return len(self), 0 with open(self.fn) as f: str = f.read(self.lastfilesize) md5 = self.hashlib.md5(str.encode('utf-8')) digest = md5.digest() if digest == self.lastdigest: numoldstats = len(self) else: self.loadstr(str, reset=1) numoldstats = 0 str = f.read() self.laststat = self.os.fstat(f.fileno()) self.lastfilesize = self.laststat.st_size md5.update(str.encode('utf-8')) self.lastdigest = md5.digest() self.loadstr(str) numnewstats = len(self.stats)-numoldstats return numoldstats, numnewstats def open(self, fn): if not fn: self.len_stats = 0 self.stats = [] self.max_size = 0 self.fn = fn return with open(fn) as f: str = f.read() lastdigest = self.hashlib.md5(str.encode('utf-8')).digest() laststat = self.os.fstat(f.fileno()) self.loadstr(str, reset=1) # Update these only if there was no exception so far. self.fn = fn self.lastdigest = lastdigest self.laststat = laststat self.lastfilesize = laststat.st_size def loadstr(self, str, reset=0): stats = [] lines = str.split('\n') del str linesiter = iter(lines) max_size = 0 while 1: try: st = self.mod.Use.load(linesiter) except StopIteration: break stats.append(st) if st.size > max_size: max_size = st.size # Only update self if there were no exception so far if reset: self.stats = [] self.max_size = 0 self.max_size = max(self.max_size, max_size) self.stats.extend(stats) self.len_stats = len(self.stats) def __getitem__(self, idx): return self.stats[idx] def __len__(self): try: return self.len_stats except AttributeError: self.len_stats = len(self.stats) return self.len_stats def get_max_size(self): return self.max_size class ProfileRow: kindwidth = 30 def __init__(self, master, row, usecolor=1): self.master = master self.row = row if usecolor: colbg = Frame(master=master, bg='black', width=1, borderwidth=1, relief=GROOVE) self.color = Label(master=colbg, bg='white', width=1, borderwidth=1, relief=GROOVE) self.color.grid(row=0, column=0) colbg.grid(row=row, column=0, sticky=NW) self.rsizevar = SizeVar() self.rsize = Label( master=master, textvariable=self.rsizevar, width=6, anchor=E) self.rpercentvar = StringVar() # BBIntVar() self.rpercent = Label( master=master, textvariable=self.rpercentvar, width=3, anchor=E) self.dsizevar = SizeVar() self.dsize = Label( master=master, textvariable=self.dsizevar, width=6, anchor=E) self.dpercentvar = StringVar() # BBIntVar() self.dpercent = Label( master=master, textvariable=self.dpercentvar, width=3, anchor=E) self.kindvar = StringVar() self.kind = Label(master=master, textvariable=self.kindvar, anchor=NW, width=self.kindwidth, justify=LEFT) self.rsize.grid(row=row, column=1, sticky=NE) self.rpercent.grid(row=row, column=2, sticky=NE) self.dsize.grid(row=row, column=3, sticky=NE) self.dpercent.grid(row=row, column=4, sticky=NE) self.kind.grid(row=row, column=5, sticky=NW) def set_color_size_percent_kind(self, color, rsize, rpercent, dsize, dpercent, kind): self.set_color(color) if color is not None: self.set_color(color) self.rsizevar.set(rsize) if rpercent is None: rpercent = '' else: rpercent = str(int(round(rpercent))) self.rpercentvar.set(rpercent) self.dsizevar.set(dsize) dpercent = str(int(round(dpercent))) self.dpercentvar.set(dpercent) self.set_kind(kind) def set_color(self, color): self.color.configure(bg=color) def set_kind(self, kind): self.kindtext = kind if len(kind) > self.kindwidth: import textwrap kind = textwrap.fill(kind, width=self.kindwidth) self.kindvar.set(kind) def clear(self): self.set_color_size_percent_kind(self.master['bg'], 0, 0, 0, 0, '--') class AxisControl: scale_table = [1, 2, 5] while scale_table[-1] < 1e12: scale_table.append(scale_table[-3] * 10) def __init__(self, master, name, range, grid, unit, rangecommand, gridcommand, autocommand=None ): small = 0 self.name = name self.unit = unit self.range = range self.rangecommand = rangecommand self.frame = frame = Frame(master, borderwidth=2, relief=GROOVE) self.rangevar = SizeVar() self.rangevar.set(range) rangeval = Entry(master=self.frame, # anchor=E, width=4, textvar=self.rangevar, #font=('fixed', '16', 'bold'), #font=('terminal', '16', 'bold'), #font=('terminal', '14'), font=('fixed', '14'), # bg='black',fg='yellow' bg='#fdd' ) rangeval.bind('<KeyPress-Return>', self.event_range_enter) namelabel = Menubutton(frame, text=name, relief='raised', anchor=W) namemenu = Menu(namelabel) namelabel['menu'] = namemenu if autocommand: self.autovar = BooleanVar() self.autovar.set(True) namemenu.add_checkbutton( # autobutton = Checkbutton(frame, label='Auto', variable=self.autovar, command=autocommand, # relief=RAISED ) autobutton = Checkbutton(frame, text='Auto', variable=self.autovar, command=autocommand, relief=RAISED ) else: self.autovar = None if gridcommand: self.gridvar = BooleanVar() self.gridvar.set(grid) namemenu.add_checkbutton( label='Grid', variable=self.gridvar, command=lambda: gridcommand(self.gridvar.get()), ) gridbutton = Checkbutton(frame, text='Grid', variable=self.gridvar, command=lambda: gridcommand( self.gridvar.get()), relief=RAISED ) rangelabel = Label(frame, text='Range') if name == 'Y' and small: padx = 5 pady = 0 else: padx = 3 pady = 3 ud = Frame(frame) rangeup = ClickButton(ud, text='+', pady=pady, padx=padx, font=('fixed', 8), command=lambda: self.range_button(1)) rangedown = ClickButton(ud, text='-', pady=pady, padx=padx, font=('fixed', 8), command=lambda: self.range_button(-1)) rangedown.grid(row=0, column=0) rangeup.grid(row=0, column=1) row = 0 if small and name == 'Y': namelabel.grid(row=0, rowspan=1, column=0) rangeup.grid(row=0, column=1, sticky=W) autobutton.grid(row=1, column=0) rangedown.grid(row=1, column=1, sticky=W) rangeval.grid(row=2, column=0, columnspan=2, sticky=W, padx=3, pady=3) elif small and name == 'X': namelabel.grid(row=0, column=0) rangeval.grid(row=0, column=1, sticky=W, padx=3, pady=3) rangedown.grid(row=0, column=2, sticky=W) rangeup.grid(row=0, column=3, sticky=W) else: namelabel.grid(row=row, column=0, sticky=N+W, ipadx=0, ipady=0, padx=2, pady=2) rangelabel.grid(row=row, column=1, sticky=W) ud.grid(row=row, column=2, padx=2) row += 1 if gridcommand: gridbutton.grid(row=row, column=0, sticky=W) rangeval.grid(row=row, column=1, padx=3, pady=3) if autocommand: pass autobutton.grid(row=row, column=2) def cmd_range(self): pass def event_range_enter(self, event): str = self.rangevar.get() try: rng = stringsize(str) if rng not in self.scale_table: if not 1 <= rng <= self.scale_table[-1]: raise ValueError except ValueError: self.frame.bell() self.errorbox("""\ Invalid range entry. It should be a positive integer with an optional multiplier: K, M, G, or T (1000, 1e6, 1e9, 1e12) Maximum range is 1T.""") self.rangevar.set(self.range) else: if self.autovar: self.autovar.set(False) self.setrange(rng) def auto_command(self): pass def errorbox(self, msg): tkinter.messagebox.showerror(master=self.frame, message=msg) def fit(self, range): range = self.scale_by_table(range) self.setrange(range) def range_button(self, d): if self.autovar: self.autovar.set(False) self.range_change(d) def range_change(self, d): range = self.range srange = self.scale_by_table(range) if srange > range: if d > 0: d -= 1 i = self.scale_table.index(srange) i += d if i >= len(self.scale_table): i = len(self.scale_table) - 1 if i < 0: i = 0 self.setrange(self.scale_table[i]) def setrange(self, range): if range != self.range: self.range = range self.rangevar.set(range) self.rangecommand(range) def scale_by_table(self, s): # Return the scale from table that is higher or equal to s for ts in self.scale_table: if ts >= s: return ts return self.scale_table[-1] WM = 1 class Marker: def __init__(self, d, tag, name, pos, poscommand=None): self.d = d self.tag = tag self.name = name self.xmarker = pos self.butdown = 0 self.ocursor = d.ocursor self.cursor = self.ocursor self.poscommand = None self.intpos = None self.moving = 0 self.selected = 0 self.entered = 0 self.butdownselected = 0 self.motion_id = None self.create() def bind(self, sequence, function): tag = self.tag self.d.drawingarea.tag_bind(tag, sequence, function) if WM: self.xlabel.bind(sequence, function) else: self.d.xmarks.tag_bind(tag, sequence, function) def coords(self, canx): self.d.drawingarea.coords(self.tag, canx, 0, canx, -int(self.d.boty)) self.d.xmarks.coords(self.tag, canx, 10) def create(self): tag = self.tag text = self.name pos = 0 self.d.drawingarea.create_line(pos, 0, pos, 20-self.d.boty, stipple='gray12', width=4, tags=(tag,)) if WM: label = self.xlabel = Label( self.d.xmarks, text=text, padx=2, pady=2, relief=RAISED) self.d.xmarks.create_window(pos, 0, window=label, tags=(tag,)) else: self.d.xmarks.create_text(pos, 0, text=text, tags=(tag,)) self.bind('<Button-1>', self.event_button_1) self.bind('<ButtonRelease-1>', self.event_button_1_release) self.bind('<Enter>', self.event_enter) self.bind('<Leave>', self.event_leave) self.d.drawingarea.bind('<Enter>', self.event_enter_movearea, add='+') self.d.drawingarea.bind( '<Button-1>', self.event_button_1_movearea, add='+') def event_button_1(self, event): self.butdown = 1 if self.selected: self.butdownselected = 1 if self.moving: self.event_stop_move(event) else: self.butdownselected = 0 self.has_moved = 0 self.event_selected(event) self.event_start_move(event) def event_button_1_movearea(self, event): if not self.entered: self.event_deselected(event) def event_button_1_release(self, event): self.butdown = 0 if self.has_moved == self.butdownselected: if self.selected: if self.moving and not (self.disloy <= event.y_root < self.dishiy): self.event_stop_move(None) self.setcursor(self.ocursor) else: self.setcursor(self.ocursor) return self.event_deselected(event) def event_deselected(self, event): if self.selected: self.selected = 0 self.xlabel['relief'] = RAISED if self.moving: self.event_stop_move(event) def event_enter(self, event): self.entered = 1 if not self.moving: if self.selected: self.event_start_move(event) else: self.setcursor('hand2') def event_enter_movearea(self, event): if self.selected and not self.moving: self.event_start_move(event) def event_leave(self, event): self.entered = 0 if not self.moving: self.setcursor(self.ocursor) elif not (self.fraloy <= event.y_root < self.frahiy): pass def event_motion(self, event): self.has_moved = 1 inside = (self.fraloy <= event.y_root < self.frahiy) if inside != self.inside: self.inside = inside if not inside: self.out_event = event self.event_stop_move(None) if self.butdown: self.setcursor('circle') self.d.bind_motion(self.event_motion_downout) else: self.in_event = event #self.delta += self.out_event.x_root - event.x_root self.event_start_move(event) return if inside: self.moved(event) self.setxvars() def event_motion_downout(self, event): # We don't get an enter while button is pressed down # Emulate an enter if we detect entering inside = (self.fraloy <= event.y_root < self.frahiy) if inside: self.d.unbind_motion(self.event_motion_downout) self.event_enter_movearea(event) def event_selected(self, event): for m in self.d.marks: m.event_deselected(event) self.selected = 1 self.xlabel['relief'] = SUNKEN def event_start_move(self, event): self.moving = 1 self.fralox = self.d.frame.winfo_rootx() self.frahix = self.fralox + self.d.frame.winfo_width() self.fraloy = self.d.frame.winfo_rooty() self.frahiy = self.fraloy + self.d.frame.winfo_height() self.dislox = self.d.drawingarea.winfo_rootx() self.dishix = self.dislox + self.d.drawingarea.winfo_width() self.disloy = self.d.drawingarea.winfo_rooty() self.dishiy = self.disloy + self.d.drawingarea.winfo_height() self.down_event = event self.prev_event = event self.down_xmarker = self.xmarker self.down_xvfrac = self.d.drawingarea.xview()[0] self.inside = 1 self.delta = 0 self.lift() self.motion_id = self.d.bind_motion(self.event_motion) self.moved(event) def event_stop_move(self, event): assert self.moving self.moving = 0 self.d.unbind_motion(self.motion_id) if event is not None: self.moved(event) self.setxvars() if self.entered and not self.selected: self.setcursor('hand2') else: self.setcursor(self.ocursor) def lift(self): self.d.xmarks.tag_raise(self.tag) if WM: self.xlabel.lift() self.d.drawingarea.tag_raise(self.tag) def move(self, sample): canx = self.d.canxscaled(sample) self.d.xview_pos(canx) self.coords(canx) self.xmarker = sample self.lift() def moved(self, event): curx = event.x_root cury = event.y_root prevx = self.prev_event.x_root if prevx > self.dishix and curx < self.dishix: prevx = self.dishix elif prevx < self.dislox and curx > self.dislox: prevx = self.dislox markx = self.d.canxscaled(self.xmarker) - \ self.d.drawingarea.canvasx(0) + self.dislox dx = curx - prevx l = r = 1 if self.xmarker >= self.d.numstats-1: r = 0 if self.xmarker <= 0: l = 0 stop = 0 # Should we allow to move it back or not # if it is at an endpoint? # Here we don't move it at all, to make marker pos correspond # more closely with mouse position. if ((r == 0 and curx > markx) or (l == 0 and curx < markx)): l = r = 0 if self.butdown: if curx > self.dishix: l = 0 elif curx < self.dislox: r = 0 else: if not (self.dislox <= curx < self.dishix and self.disloy <= cury < self.dishiy): l = r = 0 stop = 1 if l and r: self.setcursor('sb_h_double_arrow') elif l: self.setcursor('sb_left_arrow') if dx > 0: dx = 0 elif r: self.setcursor('sb_right_arrow') if dx < 0: dx = 0 else: self.setcursor('dot') dx = 0 self.prev_event = event sample = self.d.limitx(self.xmarker + dx / self.d.xscale) canx = self.d.canxscaled(sample) self.d.xview_pos(canx) self.coords(canx) self.xmarker = sample if stop and self.moving: self.event_stop_move(None) def set(self): canx = self.d.canxscaled(self.xmarker) self.coords(canx) self.lift() def set_poscommand(self, command): self.poscommand = command self.intpos = None def setcursor(self, cursor): if cursor != self.cursor: self.xlabel['cursor'] = cursor self.cursor = cursor self.d.setcursor(cursor) def setxvars(self): if self.poscommand: intpos = int(round(self.xmarker)) if intpos != self.intpos: self.intpos = intpos self.poscommand(intpos) class Display: orgwidth = 300 orgheight = 300 minwidth = 30 minheight = 30 def __init__(self, master, scale_table, numkindrows, getkindcolor, xrange=100, yrange=100, xgrid=False, ygrid=False, graphtype='Bars', statype='Size', ): self.master = master self.scale_table = scale_table self.numkindrows = numkindrows self.getkindcolor = getkindcolor self.xrange = xrange self.yrange = yrange self.xgrid = xgrid self.ygrid = ygrid self.var_xgrid = BooleanVar() self.var_xgrid.set(xgrid) self.var_ygrid = BooleanVar() self.var_ygrid.set(ygrid) self.graphtype = graphtype self.statype = statype self.numstats = 0 self.ymaxs = [] self.ymins = [] self.ymax = 1 # To get around problems with dynamic unbinding / unbinding of motion, # I handle it myself. in the bind_motion method using the following. self.bound_motions = {} self.event_motion_id = None # self.frame = frame = Frame(master, borderwidth=3, relief=SUNKEN, # relief=GROOVE, # background='green' ) #self.frame = frame = Frame(master,background='green') bordercolor = '#ccc' screencolor = '#e0e0e0' xscrollincrement = 1 frame = Frame(self.frame) frame.grid(row=0, column=0) #move = Frame(frame, height=10,width=10,background='red', relief=RAISED) #move = Button(self.frame, height=10,width=10,background='red') self.drawingarea = C = Canvas(frame, width=self.orgwidth, height=self.orgheight, xscrollincrement=xscrollincrement, # background='black', background=screencolor, bd=0, xscrollcommand=self.xscrollbar_set, # confine=False, ) #self.yctrlframe = Frame(frame, borderwidth=2,relief=GROOVE) self.yscrollbar = Scrollbar(frame, orient=VERTICAL, width=10) # self.yscrollbar['command']=self.drawingarea.yview #self.drawingarea['yscrollcommand'] = self.yscrollbar_set # self.yscrollbar.pack(side=RIGHT,fill=Y) #self.yctrlframe.grid(row = 0, column = 0,sticky=N+S,padx=3,pady=3) self.xaxis = Canvas(frame, width=C['width'], height=20, xscrollincrement=xscrollincrement, bd=0, background=bordercolor, #xscrollcommand = self.xscrollbar_set # confine=False, ) self.xmarks = Canvas(frame, width=C['width'], height=20, xscrollincrement=xscrollincrement, bd=0, background=bordercolor, #xscrollcommand = self.xscrollbar_set # confine=False, ) self.yaxis = Canvas(frame, height=C['height'], width=50, bd=0, background=bordercolor, ) self.xscrollbar = Scrollbar(frame, orient=HORIZONTAL, command=self.drawingarea_xview, width=12, background=bordercolor, ) xy = Canvas(frame, width=50, height=20, bd=0, background=bordercolor, ) var_yrange = SizeVar() self.var_yrange = var_yrange row = 0 Label(frame, textvar=var_yrange, bd=0, relief=FLAT, background=bordercolor).grid( row=row, column=0, sticky=W+E+N+S) self.xscrollbar.grid(row=row, column=1, sticky=E+W) row += 1 self.yunit = Label(frame, text='Bytes', bd=0, relief=FLAT, background=bordercolor) self.yunit.grid( row=row, column=0, sticky=W+E+N+S) self.xmarks.grid(row=row, column=1, sticky=W+E+N) row += 1 self.yaxis.grid(row=row, column=0) C.grid(row=row, column=1, sticky=W+E) row += 1 xy.grid(row=row, column=0) self.xaxis.grid(row=row, column=1, sticky=W+E+N) self.botx = float(C['width']) self.boty = float(C['height']) self.chdim = self.getchdim() self.canx0 = 0 self.tmax = 0 self.xscale = self.botx / self.xrange self.yscale = self.boty / self.yrange self.xi0 = None xy.create_line(0, 2, 44, 2) xy.create_line(49, 6, 49, 22) xy.create_text(25, 14, text='Sample') self.setscrollregion() self.ocursor = self.drawingarea['cursor'] self.cursor = self.ocursor self.marks = [] def bind_motion(self, function): if self.event_motion_id == None: self.event_motion_id = self.frame.bind_all( '<Motion>', self.event_motion, add='+') self.bound_motions[function] = self.bound_motions.get(function, 0) + 1 return function def event_motion(self, event): for f in list(self.bound_motions.keys()): f(event) def unbind_motion(self, funcid): n = self.bound_motions[funcid] - 1 if n == 0: del self.bound_motions[funcid] else: self.bound_motions[funcid] = n def new_xmarker(self, name=None, pos=0): tag = 'M%d' % len(self.marks) if name is None: name = tag m = Marker(self, tag, name, pos) self.marks.append(m) return m def canxscaled(self, x): return x * self.xscale + self.canx0 def canyscaled(self, y): return - y * self.yscale def cmd_xgrid(self): self.xgrid = self.var_xgrid.get() self.drawxaxis() def cmd_ygrid(self): self.ygrid = self.var_ygrid.get() self.drawyaxis() def cmd_yrange_auto(self): self.ymax = None self.yrange_auto() def limitx(self, x): lo = 0 hi = max(0, self.numstats-1) if x < lo: return lo if x > hi: return hi return x def resize(self, dx, dy): x = self.botx + dx y = self.boty + dy if x < self.minwidth: x = self.minwidth dx = x - self.botx if y < self.minheight: y = self.minheight dy = y - self.boty xv = self.drawingarea.xview() yv = self.drawingarea.yview() self.drawingarea.configure(width=x, height=y) self.xaxis.configure(width=x) self.xmarks.configure(width=x) self.yaxis.configure(height=y) xscale = float(x) / self.xrange yscale = float(y) / self.yrange xscaleorg = self.drawingarea.canvasx(0) yscaleorg = 0 xq = xscale / self.xscale yq = yscale / self.yscale self.drawingarea.scale("all", xscaleorg, yscaleorg, xq, yq) #self.drawingarea.scale("barsep",xscaleorg, yscaleorg, xq, yq) #self.drawingarea.scale("xmarker",xscaleorg, yscaleorg, xq, yq) self.canx0 = xscaleorg + (self.canx0 - xscaleorg) * xq self.botx = x self.boty = y self.xscale = xscale self.yscale = yscale self.drawxaxis() self.drawyaxis() self.setscrollregion() # If the size changed much, the canvas may scroll though it shouldn't. # Notes 11 and 26 Oct 2005 . # I save the current scroll position. # The caller has to call the .moveback() method some time later. self.wantedpos = xv[0] return dx, dy def moveback(self): self.frame.update_idletasks() self.xview(MOVETO, self.wantedpos) def draw(): self.drawxaxis() self.drawyaxis() def draw_stat(self, idx, stat): graphtype = self.graphtype statype = self.statype rows = stat.get_rows_n_and_other(self.numkindrows, statype) if statype == 'Size': kindval = dict([(r.name, r.size) for r in rows]) else: kindval = dict([(r.name, r.count) for r in rows]) order = [r.name for r in rows] order.reverse() lastkindval = self.lastkindval self.lastkindval = kindval C = self.drawingarea yscale = self.yscale xscale = self.xscale x0 = idx * xscale - 0.5 * xscale + self.canx0 x1 = x0 + xscale ymax = 0 ymin = 0 y = 0 bw = 0.05*xscale ocolor = None for k in order: dy = kindval.get(k, 0) if not dy: continue color = self.getkindcolor(k) if graphtype == 'Bars': line = C.create_rectangle(x0+bw, -y*yscale, x1-bw, -(y+dy)*yscale, fill=color, outline=color, width=0, tags=("a",)) if color == ocolor: C.create_line(x0, -(y)*yscale, x1, -(y)*yscale, fill='black', tags=('barsep',)) ocolor = color y += dy elif graphtype == 'Lines': if dy > ymax: ymax = dy elif dy < ymin: ymin = dy y0 = lastkindval.get(k) if y0 is None: y0 = dy x00 = x0 else: x00 = x0 - 0.4 * xscale C.create_line(x00, - y0 * yscale, x1 - 0.6 * xscale, - dy * yscale, fill=color, tags=('a',)) C.create_line(x1 - 0.6 * xscale, - dy * yscale, x1 - 0.4 * xscale, - dy * yscale, fill=color, width=4, tags=('a',)) if graphtype == 'Bars': if y > ymax: ymax = y elif y < ymin: ymin = y assert idx == len(self.ymaxs) == len(self.ymins) self.ymaxs.append(ymax) self.ymins.append(ymin) if idx > self.tmax: self.tmax = idx def drawingarea_xview(self, cmd, what, unit=None): if cmd == 'scroll' and unit == 'units': what = int(max(2, self.xscale)*int(what)) self.xview(cmd, what, unit) def setcursor(self, cursor): if cursor != self.cursor: self.drawingarea['cursor'] = cursor self.master['cursor'] = cursor self.cursor = cursor def xmarkers_set(self): for m in self.marks: m.set() def xview(self, *args): if not args: return self.drawingarea.xview() self.drawingarea.xview(*args) self.xaxis.xview(*args) self.xmarks.xview(*args) def xview_moveto(self, fraction): self.xview(MOVETO, fraction) def xview_pos(self, pos, fraction=None, leftmargin=5, rightmargin=5): # Scroll canvas view, if necessary, so that something # (eg an x marker) at canvas position pos will be visible # with minimum specified margin at left and right. # Scroll relative to fraction; default is current xview position. if fraction is None: fraction = self.xview()[0] x1, y1, x2, y2 = self.scrollregion cc = x1 + fraction * (x2 - x1) xm = pos - cc lo = leftmargin hi = self.botx - rightmargin if xm < lo: dx = xm - lo xm = lo elif xm >= hi: dx = (xm - hi) xm = hi else: dx = 0 r = fraction + dx / float(x2 - x1) self.xview_moveto(r) def drawxaxis(self): scale_table = self.scale_table self.xaxis.delete('all') self.drawingarea.delete('xgrid') x1, y1, x2, y2 = self.scrollregion chdx, chdy = self.chdim i = 0 while (scale_table[i] * self.xscale < min(5, len(str(scale_table[i] * self.tmax))) * chdx): i += 1 self.xstep = scale_table[i] divisuf = ( (1000000000000, '%dT'), (1000000000, '%dG'), (1000000, '%dM'), (1000, '%dK'), (1, '%d') ) for divi, form in divisuf: if self.xstep >= divi: break self.xdivi = divi self.xform = form self.xi0 = 0 self.updatexaxis() def updatexaxis(self): chdx, chdy = self.chdim step = self.xstep gridon = self.xgrid for i in range(self.xi0, self.tmax+step, step): x = self.canx0 + i*self.xscale self.xaxis.create_line(x, 0, x, 4) if gridon: self.drawingarea.create_line(x, 0, x, -self.boty, tags=('xgrid',), width=2, stipple="gray25") text = self.xform % (i / self.xdivi) self.xaxis.create_text(x, chdy, text=text) self.xaxis.create_line(self.canx0 + self.xi0 * self.xscale, 1, x+self.xscale, 1) self.xi0 = i self.xmarkers_set() def drawyaxis(self): gridon = self.ygrid self.yaxis.delete('all') self.drawingarea.delete('ygrid') chdx, chdy = self.getchdim() width = int(self.yaxis['width']) i = 0 maxval = self.yrange while (self.scale_table[i] * self.yscale < 1.5 * chdy): i += 1 step = self.scale_table[i] divisuf = ( (1000000000000, '%4dT'), (1000000000, '%4dG'), (1000000, '%4dM'), (1000, '%4dK'), (1, '%5d') ) for divi, form in divisuf: if step >= divi: break for i in range(0, maxval+step, step): y = - i*self.yscale self.yaxis.create_line(width-3, y, width-1, y) if gridon: self.drawingarea.create_line(self.scrollregion[0], y, self.scrollregion[2], y, stipple="gray25", tags=('ygrid',)) text = form % (i / divi) self.yaxis.create_text(chdx*2.5, y-0.5*chdy, text=text) #self.yaxis.create_text(chdx*2.5, 0.5*chdy, text='bytes') self.yaxis.create_line(width-1, 0, width-1, -self.boty) self.xmarkers_set() def getchdim(self): ch = self.xaxis.create_text(0, 0, text='0') x1, y1, x2, y2 = self.xaxis.bbox(ch) self.xaxis.delete(ch) chdx = abs(x2 - x1) chdy = abs(y2 - y1) return chdx, chdy def load_stats(self, stats): ocursor = self.frame.winfo_toplevel()['cursor'] try: self.frame.winfo_toplevel()['cursor'] = 'watch' self.frame.update() self.numstats = len(stats) self.lastkindval = {} self.tmax = 0 self.ymax = None self.ymaxs = [] self.ymins = [] C = self.drawingarea C.delete('barsep') C.delete('a') for (i, st) in enumerate(stats): self.draw_stat(i, st) try: self.drawingarea.tag_raise('barsep', 'a') except TclError: pass # May be 'tagOrId "a" doesn't match any items' if empty! self.drawxaxis() self.drawyaxis() self.xmarkers_set() self.yrange_auto() finally: self.frame.winfo_toplevel()['cursor'] = ocursor def add_stats(self, stats): for (i, st) in enumerate(stats): self.draw_stat(i+self.numstats, st) self.numstats += len(stats) self.updatexaxis() self.setscrollregion() def setxgrid(self, grid): self.xgrid = grid self.drawxaxis() def setygrid(self, grid): self.ygrid = grid self.drawyaxis() def setgraphtype(self, gmode, stats): graphtype, statype = gmode.split(' ') if graphtype != self.graphtype or statype != self.statype: self.graphtype = graphtype self.statype = statype if statype == 'Size': self.yunit['text'] = 'Bytes' elif statype == 'Count': self.yunit['text'] = 'Objects' else: raise ValueError self.load_stats(stats) def setscrollregion(self): C = self.drawingarea botx = self.botx x1 = self.canx0 x2 = self.tmax * self.xscale + self.canx0 x1extra = botx / 2 + 2 # max(5, self.xscale*0.5) x2extra = botx / 2 + 2 # max(5, self.xscale*0.5) x1 -= x1extra x2 += x2extra y1 = 1-self.boty y2 = 1 self.scrollregion = (x1, y1, x2, y2) C.configure(scrollregion=self.scrollregion) self.xaxis.configure(scrollregion=(x1, 0, x2, 10)) self.xmarks.configure(scrollregion=(x1, 0, x2, 20)) self.yaxis.configure(scrollregion=(0, y1, 20, y2)) self.drawingarea.yview(MOVETO, 0.0) def setxrange(self, xrange): dxrange = self.xrange / float(xrange) self.xrange = xrange xscaleorg = self.drawingarea.canvasx(self.botx/2) self.drawingarea.scale("a", xscaleorg, 0, dxrange, 1.0) self.drawingarea.scale("barsep", xscaleorg, 0, dxrange, 1.0) self.canx0 = xscaleorg + (self.canx0 - xscaleorg) * dxrange self.xscale = self.botx / float(self.xrange) self.setxscrollincrement(max(2, self.xscale)) self.drawxaxis() self.setscrollregion() def setxscrollincrement(self, dx): return self.drawingarea.configure(xscrollincrement=dx) self.xaxis.configure(xscrollincrement=dx) self.xmarks.configure(xscrollincrement=dx) def setyrange(self, yrange): dyrange = float(self.yrange) / yrange self.yrange = yrange self.var_yrange.set(yrange) self.drawingarea.scale("a", 0, 0, 1.0, dyrange) self.drawingarea.scale("barsep", 0, 0, 1.0, dyrange) self.yscale = float(self.boty) / self.yrange self.drawingarea.yview(MOVETO, 0.0) self.drawyaxis() def xscrollbar_set(self, first, last): self.xscrollbar.set(first, last) self.yrange_auto() def yrange_auto(self, force=0): if force or self.ycontrol.autovar.get(): lo = max(0, int(0.5+(self.drawingarea.canvasx(0) - self.canx0) / self.xscale)) hi = min(len(self.ymaxs), int(1.5+(self.drawingarea.canvasx(self.botx) - self.canx0) / self.xscale)) if lo == hi: ymax = 1 else: ymax = max(self.ymaxs[lo:hi]) if ymax != self.ymax: self.ymax = ymax self.ycontrol.fit(ymax) class MarkerControl: def __init__(self, master, marker, setcommand=lambda: 0 ): self.sample = 0 self.numsamples = 0 self.setcommand = setcommand self.marker = marker self.name = marker.name sf = self.frame = Frame(master, borderwidth=2, relief=GROOVE) self.samplevar = SizeVar() Label(sf, text='%s sample' % marker.name).grid(row=0, column=0) Label(sf, textvariable=self.samplevar, font=('terminal', '16', 'bold'), bg='black', fg='yellow' ).grid(row=1, column=0, padx=3, pady=3) ClickButton(sf, text='-', pady=0, padx=5, command=lambda: self.changesample(-1)).grid(row=0, column=1, sticky=E) ClickButton(sf, text='+', pady=0, padx=5, command=lambda: self.changesample(1)).grid(row=0, column=2, sticky=W) self.trackingvar = BooleanVar() self.trackbutton = Checkbutton( sf, text='Track', padx=5, variable=self.trackingvar, relief=RAISED, command=self.settracking, indicatoron=1, ) self.trackbutton.grid(row=1, column=1, columnspan=2) def changesample(self, d): sample = self.sample + d if 0 <= sample < self.numsamples: self.setmarker(sample) def setmarker(self, sample): self.marker.move(sample) self.setsample(sample) def setnumsamples(self, num): self.numsamples = num if self.trackingvar.get() or self.sample >= self.numsamples: self.setmarker(max(0, self.numsamples-1)) def setsample(self, sample): self.sample = sample self.samplevar.set(sample) self.setcommand() def settracking(self, tracking=None): if tracking is not None: self.trackingvar.set(tracking) else: tracking = self.trackingvar.get() if tracking: self.setmarker(max(0, self.numsamples-1)) class Window: def __init__(self, app, frame, windowmenu=None): self.app = app self.frame = frame self.windowmenu = windowmenu self.wtitle = frame.title() self._is_destroyed = 0 # Binding to <destroy> didnt work well: # frame.bind('<Destroy>', self.event_destroy, add='+') # I give up. I modify .destroy of frame argument instead. self.old_destroy = frame.destroy frame.destroy = self.new_destroy def new_destroy(self): if self._is_destroyed: return self._is_destroyed = 1 self.app.del_window(self) try: self.old_destroy() except TclError: # This may happen at closing last window # because exit destroys the root when it sees all windows were closed. # So I ignore it. pass def title(self, title): self.frame.title(title) self.frame.iconname(title) self.wtitle = title self.app.chg_window(self) def wakeup(self): frame = self.frame try: if frame.wm_state() == "iconic": frame.wm_deiconify() frame.tkraise() # I don't think I want .focus_set: it behaved strange in X at least. # frame.focus_set() except TclError: # This can happen when the window menu was torn off. # Simply ignore it. pass class WindowMenu: def __init__(self, frame, variable): self.button = Menubutton(frame, text='Window') self.menu = Menu(self.button) self.button['menu'] = self.menu self.variable = variable self.wmap = {} def add_window(self, window): self.menu.add_radiobutton( command=window.wakeup, label='%d %s' % (window.wid, window.wtitle), value=window.wid, variable=self.variable) self.wmap[window.wid] = self.menu.index(END) def chg_window(self, window): self.menu.delete(self.wmap[window.wid]) self.menu.insert_radiobutton( self.wmap[window.wid], command=window.wakeup, label='%d %s' % (window.wid, window.wtitle), value=window.wid, variable=self.variable) def del_window(self, window): idx = self.wmap[window.wid] del self.wmap[window.wid] try: self.menu.delete(idx) except TclError: # This can happen if the menu was destroyed before its contents. # Simply ignore it. pass for wid in list(self.wmap.keys()): if self.wmap[wid] > idx: self.wmap[wid] -= 1 class ProfileApp: def __init__(self, mod): self.mod = mod root = Tk() self.root = root root.withdraw() self.windows = {} self.windowmenus = {} self.var_window = IntVar(root) def add_window(self, window): window.wid = max([0]+list(self.windows.keys()))+1 self.windows[window.wid] = window wm = getattr(window, 'windowmenu', None) if wm: self.windowmenus[window.wid] = wm for w in list(self.windows.values()): if w is not window: wm.add_window(w) for wm in list(self.windowmenus.values()): wm.add_window(window) self.var_window.set(window.wid) window.frame.bind('<FocusIn>', lambda event: self.var_window.set(window.wid), add='+') window.frame.bind('<Deactivate>', lambda event: self.var_window.set(0), add='+') def add_window_frame(self, frame, windowmenu=None): w = Window(self, frame, windowmenu) self.add_window(w) return w def chg_window(self, window): for wm in list(self.windowmenus.values()): wm.chg_window(window) def del_window(self, window): wid = window.wid if getattr(window, 'windowmenu', None): del self.windowmenus[wid] del self.windows[wid] for wm in list(self.windowmenus.values()): wm.del_window(window) if not self.windows: self.exit() def exit(self): try: self.root.destroy() except TclError: pass self.root.quit() def mainloop(self): return self.root.mainloop() def new_profile_browser(self, filename): return ProfileBrowser(self, filename) class PaneDiv: def __init__(self, master, movecommand): self.frame = frame = Frame(master) self.movecommand = movecommand self.butsize = bs = 6 bc = self.butcent = bs / 2 + 3 h = 10 self.top = Canvas( frame, width=10, height=h, ) self.top.create_line( bc, 0, bc, h, fill='#808080', width=1) self.top.create_line( bc+1, 0, bc+1, h, fill='white', width=1) self.rsbut = Canvas( frame, cursor='crosshair', width=self.butsize, height=self.butsize, relief=RAISED, bd=2 ) self.bot = Canvas( frame, width=10, height=300, bd=0 ) self.top.grid(row=0, column=0, sticky=N) self.rsbut.grid(row=1, column=0, sticky=N) self.bot.grid(row=2, column=0, sticky=N) self.rsbut.bind('<Button-1>', self.but_down) self.rsbut.bind('<ButtonRelease-1>', self.but_up) def but_down(self, event): self.down_event = event self.rsbut.configure(relief=SUNKEN) def but_up(self, event): self.rsbut.configure(relief=RAISED) dx = event.x - self.down_event.x self.movecommand(dx) def setheight(self, height): h = height - 18 self.bot['height'] = h bc = self.butcent self.bot.create_line( bc, 0, bc, h, fill='#808080', width=1) self.bot.create_line( bc+1, 0, bc+1, h, fill='white', width=1) class TableFrame: def __init__(self, graph, master, numkindrows, samplevar): self.graph = graph self.mod = graph.mod frame = self.frame = Frame(master, borderwidth=2, relief=GROOVE) row = 0 self.marktime = StringVar() self.totsizevar = SizeVar() self.sampler = StringVar() self.sampler.set('R') fr = Frame(frame) # For header om = OptionMenu(fr, self.sampler, 'R', 'L', 'R-L') om.grid(row=0, column=0, sticky=W) Label(fr, text='Sample').grid(row=0, column=1, sticky=W) Label(fr, textvariable=samplevar, background='black', foreground='yellow', ).grid(row=0, column=2, sticky=W, pady=3) Label(fr, text='at').grid(row=0, column=3, sticky=W) Label(fr, textvariable=self.marktime).grid( row=0, column=4, sticky=W) Label(fr, text='Total size = ').grid( row=1, column=0, columnspan=3, sticky=W) Label(fr, textvar=self.totsizevar).grid( row=1, column=3, columnspan=2, sticky=W) fr.grid(row=row, column=0, sticky=W) row += 1 orow = row tb = Frame(frame) row = 0 Label(tb, text="").grid(row=row, column=0) Label(tb, text="R", ).grid(row=row, column=1, sticky=E) Label(tb, text="%R").grid(row=row, column=2, sticky=E) Label(tb, text="R-L", ).grid(row=row, column=3, sticky=E) Label(tb, text="%L").grid(row=row, column=4, sticky=E) Label(tb, text="Kind").grid(row=row, column=5, sticky=W) row += 1 self.profrows = [] self.totrow = ProfileRow(tb, row) self.profrows.append(self.totrow) row += 1 for i in range(numkindrows+1): profrow = ProfileRow(tb, row) self.profrows.append(profrow) row += 1 row = orow tb.grid(row=row, column=0, sticky=W) # for next.. row += 1 self.totresize = 0 self.kindwidth = ProfileRow.kindwidth def resize(self, dx, dy): dx = int(dx) self.totresize += dx charresize, extra = divmod(self.totresize, 7) newwidth = ProfileRow.kindwidth + charresize oldwidth = self.profrows[0].kind['width'] if newwidth < 10: newwidth = 10 dx = (newwidth - oldwidth) * 7 + extra for pr in self.profrows: pr.kind['width'] = newwidth pr.kindwidth = newwidth pr.kind['padx'] = extra / 2 import textwrap kindtext = textwrap.fill(pr.kindtext, width=pr.kindwidth) pr.set_kind(pr.kindtext) return dx, dy def update(self, lsamp, rsamp): self.marktime.set(self.mod.time.asctime( self.mod.time.localtime(rsamp.stat.timemade))) return for pr in self.profrows: pr.clear() rdiv = float(rsamp.stat.size) ldiv = float(lsamp.stat.size) self.totrow.set_color_size_percent_kind( None, rsamp.stat.size, 100.0, rsamp.stat.size - lsamp.stat.size, (rsamp.stat.size - lsamp.stat.size) * 100.0 / ldiv, '<Total>' ) for i, r in enumerate(rsamp.rows): l = lsamp.kindrows[r.name] self.profrows[i+1].set_color_size_percent_kind( self.graph.getkindcolor(r.name), r.size, r.size * 100.0 / rdiv, r.size - l.size, (r.size - l.size) * 100.0 / ldiv, r.name) class ColSpec: def __init__(self, tf, header, width, pos, render, idx=()): self.tf = tf self.header = header self.name = header self.width = width self.pos = pos self.render = render self.idx = idx def align(self, text): sp = ' '*(self.width - len(text)) if self.pos == LEFT: text = text + sp elif self.pos == RIGHT: text = sp[:-1] + text + ' ' else: assert 0 assert len(text) == self.width return text class TableFrame: def __init__(self, graph, master): self.graph = graph self.mod = graph.mod frame = self.frame = Frame( master, borderwidth=3, relief=SUNKEN ) self.colspecs = {} self.colwidths = [] def defcol(names, width, pos, put, idxfunc=lambda x: ()): if callable(put): put = [put]*len(names) self.colwidths.append(width) for name, put in zip(names, put): spec = ColSpec(self, name, width, pos, put, idxfunc(name)) self.colspecs[name] = spec defcol(('A', 'B'), 2, LEFT, self.putcolor, lambda x: x) defcol(('Size', 'Count'), 7, RIGHT, [self.putsize, self.putcount]) defcol(('%A:Tot', '%B:Tot'), 7, RIGHT, self.putpercent, lambda name: name[1]) defcol(('B-A', 'A-B', 'Cumul'), 7, RIGHT, [self.putdiff, self.putdiff, self.putcumul], lambda name: [(), name.split('-')]['-' in name]) defcol(('%A:Tot', '%B:Tot'), 7, RIGHT, self.putpercent, lambda name: name[1]) defcol(('Kind',), 20, LEFT, self.putkind) width = 0 for w in self.colwidths: width += w self.totxresize = 0 self.totyresize = 0 self.kindcol = self.colspecs['Kind'] self.orgkindwidth = self.kindcol.width self.widthbeforekind = width - self.orgkindwidth self.minkindwidth = 10 self.mintextheight = 2 width += 1 self.width = self.orgwidth = width wrap = NONE cursor = master['cursor'] relief = FLAT self.minpadx = 3 self.tothead = Text( frame, width=width, wrap=wrap, background='#ccc', height=2, padx=self.minpadx, relief=relief, cursor=cursor, ) self.rowhead = Text( frame, width=width, wrap=wrap, background='#ccc', height=1, padx=self.minpadx, relief=relief, cursor=cursor, ) self.tsframe = Frame(frame) self.textminpady = 2 self.text = Text( self.tsframe, width=width, wrap=wrap, height=21, background='#e0e0e0', relief=relief, takefocus=0, cursor=cursor, padx=self.minpadx, pady=self.textminpady, ) self.scrollbar = Scrollbar( self.tsframe, width=10, orient=VERTICAL, command=self.text.yview ) self.scrollbar_totwidth = int( self.scrollbar['width']) + 6 # width + padding self.uses_scrollbar = 0 self.auto_scrollbar = 1 self.orgtextheight = int(self.text['height']) padx = 0 pady = 0 self.tothead.pack(anchor=N+W, padx=padx, pady=pady) self.rowhead.pack(anchor=N+W, padx=padx, pady=pady) self.text.pack(side=LEFT, anchor=N+W, padx=padx, pady=pady) self.tsframe.pack(anchor=N+W, padx=padx, pady=pady) def setchdim(self): self.text.update() self.chdx = float(self.text.winfo_width()) / self.width self.chdy = float(self.text.winfo_height()) / self.orgtextheight self.chdx = int(round(self.chdx)) self.chdy = int(round(self.chdy)) self.pixwidth = self.width * self.chdx self.pixheight = self.width * self.chdy def putcolor(self, col): if self.colorow.name == '<Total>': text = col.align(' ') color = '#e0e0e0' else: color = self.graph.getkindcolor(self.colorow.name), text = col.align('@') self.text.insert('end', text, (color,)) self.text.tag_config(color, foreground=color, background='#e0e0e0', font=('terminal', '12', 'bold'),) def putcount(self, col): self.valmode = 'Count' count = self.colorow.count self.cumulval += count self.putval(col, count) def putsize(self, col): self.valmode = 'Size' size = self.colorow.size self.cumulval += size self.putval(col, size) def putval(self, col, val): self.curval = val self.ap(col.align(sizestring(val))) def putpercent(self, col): a = self.statbyname[col.idx] if self.valmode == 'Count': ref = a.count elif self.valmode == 'Size': ref = a.size if ref: ps = percentstring(self.curval * 100.0 / ref) else: ps = '---' self.ap(col.align(ps)) def putdiff(self, col): a, b = self.rowbyname[col.idx[0]], self.rowbyname[col.idx[1]] if self.valmode == 'Count': a, b = a.count, b.count elif self.valmode == 'Size': a, b = a.size, b.size self.putval(col, a - b) def putcumul(self, col): self.putval(col, self.cumulval) def putkind(self, col): # Must be last! import textwrap wraplines = textwrap.wrap(self.colorow.name, width=col.width) self.ap(col.align(wraplines[0])) if len(wraplines) > 1: initial = '\n'+' '*(self.widthbeforekind) for line in wraplines[1:]: self.ap(initial+col.align(line)) def setmode(self, mode, numkindrows): self.mode = mode self.numkindrows = numkindrows self.mcontrols = self.graph.mcontrolbyname self.stats = self.graph.stats self.cols = [self.colspecs[x.strip()] for x in mode.split(' ') if x.strip()] self.controlnames = {} name = self.cols[0].idx self.colorcontrol = self.mcontrols[name] self.controlnames[name] = 1 self.controls = [self.colorcontrol] self.lastidxs = [None] for i, co in enumerate(self.cols): idx = co.idx if not isinstance(idx, (tuple, list)): idx = (idx,) for idx in idx: if idx not in self.controlnames: self.controls.append(self.mcontrols[idx]) self.controlnames[idx] = 1 self.lastidxs.append(None) def setscrollbar(self, sb): if sb == self.uses_scrollbar: return self.uses_scrollbar = sb w = self.scrollbar_totwidth if sb: self.resize(-w, 0, setscrollbar=0) self.scrollbar.pack(side=LEFT, fill=Y) self.text['yscrollcommand'] = self.scrollbar.set else: self.resize(w, 0, setscrollbar=0) self.scrollbar.pack_forget() self.text['yscrollcommand'] = None def update_simple(self, lsamp, rsamp): t = self.text t.delete('1.0', '100.0') t.insert('1.0', str(rsamp.stat)) def update(self, force=0, setscrollbar=1): stats = self.stats idxs = [max(0, min(control.sample, len(stats)-1)) for control in self.controls] if (idxs == self.lastidxs) and not force: return self.lastidxs = idxs self.text['state'] = self.tothead['state'] = self.rowhead['state'] = NORMAL self.text.delete('1.0', END) self.tothead.delete('1.0', END) self.rowhead.delete('1.0', END) if not stats: self.tothead.insert('end', '-- No Sample --') self.text['state'] = self.tothead['state'] = self.rowhead['state'] = DISABLED return self.statbyname = {} statbyidx = [] for i, control in enumerate(self.controls): stat = stats[idxs[i]] statbyidx.append(stat) self.statbyname[control.name] = stat samps = self.samps = [ Sample(self.mod, statbyidx[0], self.controls[0].marker.name, idxs[0], numkindrows=self.numkindrows, statype=self.graph.display.statype )] self.colorsamp = samps[0] if len(self.controls) > 1: samps.append(Sample(self.mod, statbyidx[1], self.controls[1].marker.name, idxs[1], relative=samps[0])) self.relsamp = samps[1] t = self.tothead n = max([len(str(samp.index)) for samp in samps]) for samp in samps: t.insert('end', 'Sample %s: ' % samp.name) t.insert('end', ('%%%dd' % n) % samp.index, ('index',)) t.insert('end', ' at %s\n' % (samp.datetime)) t.tag_configure('index', background='#e0e0e0') t = self.rowhead self.sizes = [float(samp.stat.size) for samp in samps] for col in self.cols: t.insert('end', col.align(col.header), ('header',)) t.insert('end', '\n') t = self.text self.ap = lambda text: t.insert('end', text) self.colorow = Row(samps[0].count, samps[0].size, '<Total>') self.rowbyname = self.statbyname self.cumulval = 0 for col in self.cols: col.render(col) self.ap('\n\n') self.cumulval = 0 for i, a in enumerate(samps[0].rows): self.colorow = a if len(samps) > 1: self.rowbyname = { samps[0].name: a, samps[1].name: samps[1].kindrows[a.name] } for col in self.cols: col.render(col) self.ap('\n') if setscrollbar and self.auto_scrollbar: numrows = int(self.text.index('end').split('.')[0])-2 h = int(self.text['height']) needs_scrollbar = numrows > h if needs_scrollbar != self.uses_scrollbar: self.setscrollbar(needs_scrollbar) self.text['state'] = self.tothead['state'] = self.rowhead['state'] = DISABLED def resize(self, dx, dy, setscrollbar=1): dx = int(dx) oldwidth = self.pixwidth newwidth = self.pixwidth + dx if newwidth < self.chdx * 2: newwidth = self.chdx * 2 self.pixwidth = newwidth dx = newwidth - oldwidth charwidth, extra = divmod(newwidth, self.chdx) self.kindcol.width = max( charwidth - self.widthbeforekind - 1, self.minkindwidth) self.totxresize += dx for t in (self.tothead, self.rowhead, self.text): t['width'] = charwidth t['padx'] = self.minpadx + extra / 2 dy = int(dy) rowresize, extra = divmod(self.totyresize + dy, self.chdy) newheight = self.orgtextheight + rowresize oldheight = int(self.text['height']) if newheight < self.mintextheight: newheight = self.mintextheight dy = (newheight - oldheight) * self.chdy + extra self.totyresize += dy self.text['height'] = newheight self.text['pady'] = self.textminpady + extra / 2 self.update(force=1, setscrollbar=1) return dx, dy class Filler: def __init__(self, master): self.frame = self.can = Canvas( master, # background='blue', width=0, height=0) def getsize(self): return int(self.can['width']), int(self.can['height']), def setsize(self, w, h): self.can.configure( width=w, height=h ) def resize(self, dw, dh): w, h = self.getsize() self.setsize(max(0, w + dw), max(0, h + dh)) class Row: def __init__(self, count, size, name): self.count = count self.size = size self.name = name class Sample: def __init__(self, mod, stat, name, index, numkindrows=None, statype='Size', relative=None): self.stat = stat self.size = stat.size self.count = stat.count self.name = name self.index = index self.datetime = mod.time.asctime(mod.time.localtime(stat.timemade)) self.kindrows = {} if numkindrows is not None: rows = stat.get_rows_n_and_other(numkindrows, statype) for r in rows: self.kindrows[r.name] = r else: kinds = [] oidx = None for row in relative.rows: if row.name == '<Other>': oidx = len(kinds) continue else: kinds.append(row.name) rows = stat.get_rows_of_kinds(kinds) size = 0 count = 0 for i, row in enumerate(rows): kind = kinds[i] if row is None: row = Row(0, 0, kind) self.kindrows[kind] = row size += row.size count += row.count if oidx is not None: other = Row(stat.count - count, stat.size - size, '<Other>') rows[oidx:oidx] = [other] self.kindrows['<Other>'] = other self.rows = rows class ProfileBrowser: colors = ("red", "green", "blue", "yellow", "magenta", "cyan", 'white') numkindrows = 10 def __init__(self, app, filename): self.inited = 0 self.app = app self.mod = mod = app.mod self.master = master = app.root if filename: filename = mod.path.abspath(filename) self.initialdir = mod.path.dirname(filename) else: self.initialdir = mod.os.getcwd() self.frame = frame = Toplevel( master, # background='#bbb' ) #frame['cursor'] = 'umbrella' # frame.resizable(True,True) self.menubar = Frame(self.frame, relief=RAISED, bd=2) self.filebutton = Menubutton(self.menubar, text='File') self.filemenu = Menu(self.filebutton) self.filebutton['menu'] = self.filemenu self.filemenu.add_command( label='New Profile Browser', command=self.cmd_new) self.filemenu.add_command(label='Open Profile', command=self.cmd_open) self.filemenu.add_command(label='Close Window', command=self.cmd_close) self.filemenu.add_command( label='Clear Cache', command=self.cmd_clear_cache) self.filemenu.add_command(label='Exit', command=self.cmd_exit) self.panebutton = Menubutton(self.menubar, text='Pane') self.panemenu = Menu(self.panebutton) self.panebutton['menu'] = self.panemenu choices = [ ('Bars', 'Lines'), ('Size', 'Count'), ] self.graphtypevar = StringVar() self.graphbutton = self.modechooser( self.menubar, 'Graph', choices, self.graphtypevar, self.cmd_graphtype) choices = [ ('A', 'B'), ('Size', 'Count'), ('%A:Tot', '%B:Tot'), ('Cumul', 'A-B', 'B-A'), ('%A:Tot', '%B:Tot'), ('Kind',), ] self.var_tablemode = StringVar() self.tablebutton = Menubutton(self.menubar, text='Table') self.tablemenu = Menu(self.tablebutton) self.tablebutton['menu'] = self.tablemenu self.headermenu = Menu(self.tablebutton, title='Table header') self.addmodechooser( self.headermenu, choices, self.var_tablemode, self.cmd_tablemode ) self.tablemenu.add_cascade(label='Header', menu=self.headermenu) self.var_tablescrollbar = StringVar() self.tablescrollbarmenu = Menu( self.tablebutton, title='Table scrollbar') self.addmodechooser( self.tablescrollbarmenu, [('Auto', 'On', 'Off')], self.var_tablescrollbar, self.cmd_tablescrollbar ) self.tablemenu.add_cascade( label='Scrollbar', menu=self.tablescrollbarmenu) self.windowmenu = WindowMenu(self.menubar, self.app.var_window) self.window = app.add_window_frame(self.frame, self.windowmenu) self.helpbutton = Menubutton(self.menubar, text='Help') self.helpmenu = Menu(self.helpbutton) self.helpbutton['menu'] = self.helpmenu self.helpmenu.add_command(label='About', command=self.cmd_about) self.helpmenu.add_command(label='Help', command=self.cmd_help) self.ctrlframe = Frame( self.frame, bd=2, relief=GROOVE, # background='#999', ) self.exitbutton = Button(self.ctrlframe, text='Exit', command=self.cmd_exit, background='red') self.set_filename(filename) self.id_collect = None self.collecting = IntVar() self.collecting.set(0) self.collectbutton = Checkbutton(self.ctrlframe, text='Collect', variable=self.collecting, command=self.cmd_collect, relief=RAISED) self.stats = Stats(self.mod) self.disptab = Frame(self.frame, # relief=SUNKEN, # bd=3 ) self.display = Display(self.disptab, scale_table=AxisControl.scale_table, numkindrows=self.numkindrows, getkindcolor=self.getkindcolor, ) self.xcontrol = AxisControl(self.ctrlframe, name='X', range=self.display.xrange, grid=self.display.xgrid, unit='samples', rangecommand=self.display.setxrange, gridcommand=self.display.setxgrid ) self.ycontrol = AxisControl(self.ctrlframe, name='Y', range=self.display.yrange, grid=self.display.ygrid, unit='bytes', rangecommand=self.display.setyrange, gridcommand=self.display.setygrid, autocommand=self.display.cmd_yrange_auto ) self.display.xcontrol = self.xcontrol self.display.ycontrol = self.ycontrol self.mcontrols = [] self.mcontrolbyname = {} for name in ('A', 'B'): marker = self.display.new_xmarker(name) control = MarkerControl( self.ctrlframe, marker, self.update_tableframe) marker.set_poscommand(control.setsample) self.mcontrols.append(control) self.mcontrolbyname[name] = control self.var_showcontrol = BooleanVar() self.var_showcontrol.set(1) self.panemenu.add_checkbutton( label='Show Control Panel', variable=self.var_showcontrol, command=self.cmd_showcontrol) self.var_showgraph = BooleanVar() self.var_showgraph.set(1) self.panemenu.add_checkbutton( label='Show Graph', variable=self.var_showgraph, command=self.cmd_showgraph) self.var_showtable = BooleanVar() self.var_showtable.set(1) self.panemenu.add_checkbutton( label='Show Table', variable=self.var_showtable, command=self.cmd_showtable) tf = self.tf = TableFrame(self, self.disptab) d_t = self.d_t = PaneDiv(self.disptab, movecommand=self.cmd_dt_moved) self.xcontrol.frame.grid(row=0, column=0, padx=3, pady=3, sticky=W) self.ycontrol.frame.grid(row=1, column=0, padx=3, pady=3) self.mcontrols[0].frame.grid( row=0, column=1, columnspan=1, sticky=W, padx=3, pady=3) self.mcontrols[1].frame.grid( row=1, column=1, columnspan=1, sticky=W, padx=3, pady=3) self.exitbutton.grid(row=0, column=2, padx=3, pady=3) self.collectbutton.grid(row=0, column=3, padx=3, pady=3) self.filler = Filler(self.frame) self.filebutton.pack(side=LEFT) self.panebutton.pack(side=LEFT) self.graphbutton.pack(side=LEFT) self.tablebutton.pack(side=LEFT) self.windowmenu.button.pack(side=LEFT) self.helpbutton.pack(side=LEFT) self.menubar.grid(column=0, columnspan=4, sticky=N+W+E) self.gridmain() frame.bind('<Map>', self.event_map) self.tf.setmode(self.var_tablemode.get(), self.numkindrows) self.load_filename(filename) d_t.frame.update_idletasks() d_t.setheight(max(self.display.frame.winfo_height(), tf.frame.winfo_height())) d_t.frame.update_idletasks() self.minsize = (500, 400) self.maxsize = (self.frame.winfo_screenwidth(), self.frame.winfo_screenheight()) minsizes = { # (ctrl, disp, tab) : (width, height) (0, 0, 0): (270, 25), (1, 0, 0): (363, 61), (0, 1, 0): (270, 131), (1, 1, 0): (270, 131), } self.setusergeometry() def initfinal(): self.tf.setchdim() rx = self.frame.winfo_rootx() + self.frame.winfo_width() self.tf_wanted_margin = rx - \ (self.tf.frame.winfo_rootx() + self.tf.frame.winfo_width()) self.lastw = self.frame.winfo_width() self.lasth = self.frame.winfo_height() self.in_configure = 0 frame.bind('<Configure>', self.event_configure) self.inited = 1 initfinal() # self.frame.after_idle(initfinal) def cmd_about(self): self.cmd_help('about') def cmd_help(self, pickname='help'): os = self.mod.os ocursor = self.frame.winfo_toplevel()['cursor'] try: self.frame.winfo_toplevel()['cursor'] = 'watch' self.frame.update() m = self.mod.Text.gsltextviewer( self.frame, inpickle=getattr(self.mod.pbhelp, pickname) # htmloutfile='/tmp/x.html', ) self.app.add_window_frame(m) finally: self.frame.winfo_toplevel()['cursor'] = ocursor def cmd_clear_cache(self): self.stats.clear_cache() def cmd_close(self): self.frame.destroy() def cmd_collect(self, *args): # self.afterfunc() # self.frame.after(1, self.afterfunc) # Turn on button first.?? if self.collecting.get(): self.event_collect() else: if self.id_collect is not None: self.frame.after_cancel(self.id_collect) self.id_collect = None def event_collect(self): o, n = self.stats.collect() if n: if o != self.display.numstats: self.display.load_stats(self.stats) else: st = self.stats[-n:] self.display.add_stats(st) for c in self.mcontrols: c.setnumsamples(len(self.stats)) self.id_collect = self.frame.after(1000, self.event_collect) def cmd_dt_moved(self, dx): # The division between display and table panes moved. # Disable configure event handling while we are resizing. self.in_configure += 1 # Right x position of enclosing frame rx = self.frame.winfo_rootx() + self.frame.winfo_width() # Right margin between pane divider and enclosing window mx = rx - (self.d_t.frame.winfo_rootx() + self.d_t.frame.winfo_width()) # Don't move pane divider outside window dx = min(dx, mx) # Right margin between table and enclosing window # before resizing mx = rx - (self.tf.frame.winfo_rootx() + self.tf.frame.winfo_width()) dx, _ = self.display.resize(dx, 0) wanted_margin = self.tf_wanted_margin # After move mx -= dx self.tf.resize(mx - wanted_margin, 0) self.display.moveback() self.in_configure -= 1 def cmd_exit(self): self.app.exit() def cmd_graphtype(self): self.display.setgraphtype(self.graphtypevar.get(), self.stats) self.cmd_tablemode() def cmd_new(self): self.app.new_profile_browser(self.filename) def cmd_open(self): op = tkinter.filedialog.Open(self.frame, # ? Should we have default extension or not?? # defaultextension='.hpy', initialdir=self.initialdir, filetypes=[('Heapy data files', '.hpy'), ('All files', '*') ] ) filename = op.show() if filename: self.load_filename(filename) def cmd_showcontrol(self): self.grid_things() def cmd_showgraph(self): if self.var_showgraph.get() and self.var_showtable.get(): self.tf.resize(-self.tf.totxresize, 0) self.display.resize(self.display.orgwidth - self.display.botx, 0) self.display.moveback() self.grid_things() cmd_showtable = cmd_showgraph def cmd_tablemode(self): self.tf.setmode(self.var_tablemode.get(), self.numkindrows) self.tf.update() def cmd_tablescrollbar(self): tf = self.tf s = self.var_tablescrollbar.get() if s == 'Auto': tf.auto_scrollbar = 1 tf.update(force=1, setscrollbar=1) elif s == 'On': tf.auto_scrollbar = 0 tf.setscrollbar(1) elif s == 'Off': tf.auto_scrollbar = 0 tf.setscrollbar(0) else: assert 0 def setusergeometry(self): # Make the geometry of the window be user-specified # This is called after Tk has determined the size # of the window needed for the initial widget configuration. # The size is not to be changed after that, other than # on user request. # I couldn't just do frame.geometry(frame.geometry()) because, # presumably, of a bug in the Tk and/or wm I am using. I hope # this works for all systems .. Notes 26 Oct 2005. self.frame.update() g = '%dx%d+%d+%d' % ( self.frame.winfo_width(), self.frame.winfo_height(), self.frame.winfo_rootx(), self.frame.winfo_rooty()) self.frame.geometry(g) def modechooser(self, frame, name, choices, cmdvar, command): button = Menubutton(frame, text=name) menu = Menu(button) button['menu'] = menu self.addmodechooser(menu, choices, cmdvar, command) return button def addmodechooser(self, menu, choices, cmdvar, command): def setcmdvar(): cmdvar.set(' '.join([v.get() for v in vars])) def cmd(): setcmdvar() command() vars = [] for ch in choices: var = StringVar() vars.append(var) var.set(ch[0]) for a in ch: menu.add_radiobutton( command=cmd, label=a, value=a, variable=var, #font=('Courier','12', 'bold'), #font=('Helvetica','12', 'bold'), columnbreak=(a == ch[0]) ) setcmdvar() def grid_things(self): ow = self.frame.winfo_width() oh = self.frame.winfo_height() self.ctrlframe.grid_forget() self.display.frame.grid_forget() self.d_t.frame.grid_forget() self.tf.frame.grid_forget() self.disptab.grid_forget() self.filler.frame.grid_forget() self.gridmain() self.frame.update_idletasks() self.sizewidgets() def gridmain(self): row = 1 c = self.var_showcontrol.get() if c: self.ctrlframe.grid(row=row, column=0, columnspan=3, padx=3, pady=3, sticky=W) row += 1 column = 0 g = self.var_showgraph.get() t = self.var_showtable.get() gt = (g, t) if g: self.display.frame.grid(row=0, column=column, sticky=N+W, padx=3, pady=3 ) column += 1 if g and t: self.d_t.frame.grid(row=0, column=column, sticky=N+W) column += 1 if t: self.tf.frame.grid(row=0, column=column, sticky=N+W, padx=3, pady=3 ) if g or t: self.disptab.grid(row=row, column=0, sticky=N+W, # padx=3,pady=3, ) row += 1 self.filler.setsize(0, 0) self.filler.frame.grid(row=row, column=3, sticky=N+W) self.frame.resizable(1, 1) def event_configure(self, event): if event.widget is not self.frame: return if not self.inited: return if self.in_configure: return curw = self.frame.winfo_width() curh = self.frame.winfo_height() if curw == self.lastw and curh == self.lasth: return self.in_configure += 1 self.lastw = curw self.lasth = curh self.sizewidgets() self.in_configure -= 1 def sizewidgets(self): self.frame.update() curw = self.frame.winfo_width() curh = self.frame.winfo_height() mbx = self.menubar.winfo_rootx() mby = self.menubar.winfo_rooty() sfs = [] if self.var_showgraph.get(): sfs.append(self.display) if self.var_showtable.get(): sfs.append(self.tf) if not sfs: sfs.append(self.filler) dys = {} didh = 0 for sf in sfs: f = sf.frame diy = f.winfo_rooty() dih = f.winfo_height() ch = diy - mby + dih dy = curh - ch - 7 didh = didh or dy dys[sf] = dy if self.var_showtable.get(): f = self.tf.frame elif self.var_showgraph.get(): f = self.display.frame else: f = self.filler.frame fx = f.winfo_rootx() fw = f.winfo_width() cw = fx - mbx + fw fdw = curw - cw - 6 if f is self.filler.frame and not self.var_showcontrol.get(): fdw = curw - self.filler.getsize()[0] - 3 if didh or fdw: if self.var_showgraph.get() and self.var_showtable.get(): dprop = float(self.display.frame.winfo_width()) dprop = dprop / (dprop + self.tf.frame.winfo_width()) dx, dy = self.display.resize(fdw * dprop, dys[self.display]) self.tf.resize(fdw - dx, dys[self.tf]) self.frame.update_idletasks() self.d_t.setheight(max(self.display.frame.winfo_height(), self.tf.frame.winfo_height())) elif self.var_showgraph.get(): self.display.resize(fdw, dys[self.display]) elif self.var_showtable.get(): self.tf.resize(fdw, dys[self.tf]) else: self.filler.resize(fdw, dys[self.filler]) self.filler.setsize(self.filler.getsize()[0], 1000) if self.var_showgraph.get(): self.display.moveback() #self.resize(dw, dh) def resize(self, dw, dh): self.display.resize(dw, dh) # self.frame.wm_geometry('') def event_map(self, event): self.frame.unbind('<Map>') self.frame.bind('<Unmap>', self.event_unmap) self.frame.lift() def event_unmap(self, event): self.frame.unbind('<Unmap>') self.frame.bind('<Map>', self.event_map) def load_filename(self, filename): ocursor = self.frame.winfo_toplevel()['cursor'] try: self.frame.winfo_toplevel()['cursor'] = 'watch' self.frame.update() if filename: filename = self.mod.path.abspath(filename) try: self.stats.open(filename) except Exception: __import__('traceback').print_exc() etype, value, tb = self.mod._root.sys.exc_info() tkinter.messagebox.showerror( master=self.frame, message=( "Error when loading\n%r:\n" % filename + "%s" % ''.join(self.mod._root.traceback.format_exception_only( etype, value))) ) else: self.display.load_stats(self.stats) for c in self.mcontrols: c.setnumsamples(len(self.stats)) # self.scontrol.trackcommand(1) self.set_filename(filename) self.xrange_fit() self.display.xview_moveto(0) self.mcontrols[1].settracking(0) self.mcontrols[0].settracking(1) self.yrange_fit() self.tf.update(force=1) if filename: self.initialdir = self.mod.path.dirname(filename) finally: self.frame.winfo_toplevel()['cursor'] = ocursor def update_tableframe(self): self.tf.update() def getkindcolor(self, kind): if kind == '<Other>': return 'black' else: return self.colors[abs(hash(kind)) % len(self.colors)] def set_filename(self, filename): self.filename = filename if not filename: filename = '<No File>' title = 'Heapy Profile Browser: %s' % filename self.window.title(title) def setnormpos(self): self.setscrollregion() if self.ymax >= self.yrange: self.yrange_fit() if self.xi0 is None: self.drawxaxis() else: self.updatexaxis() self.track() def redraw_all(self): pass def trackoff(self): self.rcontrol.settracking(0) def xrange_fit(self): self.xcontrol.fit(len(self.stats)) def yrange_fit(self): self.display.yrange_auto(force=1) class _GLUECLAMP_: _imports_ = ( '_parent:Use', '_parent:pbhelp', '_root.guppy.etc:textView', '_root:hashlib', '_root:os', '_root.os:path', '_root:time', '_root.guppy.gsl:Text', ) def pb(self, filename=None): """pb( [filename: profilefilename+]) Create a Profile Browser window. Argument filename: profilefilename+ The name of a file containing profile data. See also Heapy Profile Browser[1] Screenshot[2] References [0] heapy_Use.html#heapykinds.Use.pb [1] ProfileBrowser.html [2] pbscreen.jpg""" pa = ProfileApp(self) pa.new_profile_browser(filename) pa.mainloop() def tpg(self): self('/tmp/x.hpy')
Upload File
Create Folder