Commit d9c6da75 authored by Luke Macken's avatar Luke Macken

pep8 all the things

parent 2f5c59ac
...@@ -33,6 +33,7 @@ import warnings ...@@ -33,6 +33,7 @@ import warnings
from utils import run from utils import run
class CodeInjector(object): class CodeInjector(object):
"""Injects code into a running Python process""" """Injects code into a running Python process"""
......
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
from utils import run from utils import run
class ObjectInspector(object): class ObjectInspector(object):
"""Inspects objects in a running Python program""" """Inspects objects in a running Python program"""
......
...@@ -27,6 +27,7 @@ import pyrasite ...@@ -27,6 +27,7 @@ import pyrasite
from os.path import dirname, abspath, join from os.path import dirname, abspath, join
class PyrasiteIPC(object): class PyrasiteIPC(object):
"""Pyrasite Inter-Python Communication. """Pyrasite Inter-Python Communication.
...@@ -130,7 +131,9 @@ class PyrasiteIPC(object): ...@@ -130,7 +131,9 @@ class PyrasiteIPC(object):
self.address = address self.address = address
def cmd(self, cmd): def cmd(self, cmd):
"""Send a python command to exec in the process and return the output""" """
Send a python command to exec in the process and return the output
"""
self.send(cmd + '\n') self.send(cmd + '\n')
return self.recv() return self.recv()
......
...@@ -15,18 +15,21 @@ ...@@ -15,18 +15,21 @@
# #
# Copyright (C) 2011 Red Hat, Inc. # Copyright (C) 2011 Red Hat, Inc.
import os, sys import os
import sys
import argparse import argparse
from inject import CodeInjector from inject import CodeInjector
from utils import setup_logger from utils import setup_logger
def main(): def main():
parser = argparse.ArgumentParser( parser = argparse.ArgumentParser(
description='pyrasite - inject code into a running python process', description='pyrasite - inject code into a running python process',
epilog="For updates, visit https://github.com/lmacken/pyrasite" epilog="For updates, visit https://github.com/lmacken/pyrasite"
) )
parser.add_argument('pid', help="The ID of the process to inject code into") parser.add_argument('pid',
help="The ID of the process to inject code into")
parser.add_argument('filename', parser.add_argument('filename',
help="The second argument must be a filename") help="The second argument must be a filename")
parser.add_argument('--gdb-prefix', dest='gdb_prefix', parser.add_argument('--gdb-prefix', dest='gdb_prefix',
...@@ -58,7 +61,8 @@ def main(): ...@@ -58,7 +61,8 @@ def main():
log.error("Error: The second argument must be a filename") log.error("Error: The second argument must be a filename")
sys.exit(4) sys.exit(4)
injector = CodeInjector(pid, verbose=args.verbose, gdb_prefix=args.gdb_prefix) injector = CodeInjector(pid, verbose=args.verbose,
gdb_prefix=args.gdb_prefix)
injector.inject(filename) injector.inject(filename)
if __name__ == '__main__': if __name__ == '__main__':
......
...@@ -26,6 +26,7 @@ import threading ...@@ -26,6 +26,7 @@ import threading
from StringIO import StringIO from StringIO import StringIO
from pyrasite.ipc import PyrasiteIPC from pyrasite.ipc import PyrasiteIPC
class ReverseConnection(threading.Thread, PyrasiteIPC): class ReverseConnection(threading.Thread, PyrasiteIPC):
"""A payload that connects to a given host:port and receives commands""" """A payload that connects to a given host:port and receives commands"""
......
...@@ -61,6 +61,7 @@ open_files = [] ...@@ -61,6 +61,7 @@ open_files = []
tango = ['c4a000', 'ce5c00', '8f5902', '4e9a06', '204a87', '5c3566', tango = ['c4a000', 'ce5c00', '8f5902', '4e9a06', '204a87', '5c3566',
'a40000', '555753'] 'a40000', '555753']
def get_color(): def get_color():
used = thread_colors.values() used = thread_colors.values()
for color in tango: for color in tango:
...@@ -71,7 +72,8 @@ def get_color(): ...@@ -71,7 +72,8 @@ def get_color():
class Process(pyrasite.PyrasiteIPC, GObject.GObject): class Process(pyrasite.PyrasiteIPC, GObject.GObject):
""" """
A :class:`GObject.GObject` subclass for use in the :class:`ProcessTreeStore` A :class:`GObject.GObject` subclass that represents a Process, for use in
the :class:`ProcessTreeStore`
""" """
@property @property
...@@ -111,7 +113,7 @@ class PyrasiteWindow(Gtk.Window): ...@@ -111,7 +113,7 @@ class PyrasiteWindow(Gtk.Window):
self.resource_thread = None self.resource_thread = None
self.set_title('Pyrasite v%s' % pyrasite.__version__) self.set_title('Pyrasite v%s' % pyrasite.__version__)
self.set_default_size (600, 400) self.set_default_size(600, 400)
hbox = Gtk.HBox(homogeneous=False, spacing=0) hbox = Gtk.HBox(homogeneous=False, spacing=0)
self.add(hbox) self.add(hbox)
...@@ -131,15 +133,16 @@ class PyrasiteWindow(Gtk.Window): ...@@ -131,15 +133,16 @@ class PyrasiteWindow(Gtk.Window):
self.info_view = WebKit.WebView() self.info_view = WebKit.WebView()
self.info_view.load_string(self.info_html, "text/html", "utf-8", '#') self.info_view.load_string(self.info_html, "text/html", "utf-8", '#')
info_window = Gtk.ScrolledWindow(hadjustment = None, info_window = Gtk.ScrolledWindow(hadjustment=None, vadjustment=None)
vadjustment = None)
info_window.set_policy(Gtk.PolicyType.AUTOMATIC, info_window.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC) Gtk.PolicyType.AUTOMATIC)
info_window.add(self.info_view) info_window.add(self.info_view)
notebook.append_page(info_window, Gtk.Label.new_with_mnemonic('_Resources')) notebook.append_page(info_window,
Gtk.Label.new_with_mnemonic('_Resources'))
(stacks_widget, source_buffer) = self.create_text(True) (stacks_widget, source_buffer) = self.create_text(True)
notebook.append_page(stacks_widget, Gtk.Label.new_with_mnemonic('_Stacks')) notebook.append_page(stacks_widget,
Gtk.Label.new_with_mnemonic('_Stacks'))
self.source_buffer = source_buffer self.source_buffer = source_buffer
self.source_buffer.create_tag('bold', weight=Pango.Weight.BOLD) self.source_buffer.create_tag('bold', weight=Pango.Weight.BOLD)
...@@ -161,27 +164,27 @@ class PyrasiteWindow(Gtk.Window): ...@@ -161,27 +164,27 @@ class PyrasiteWindow(Gtk.Window):
obj_tree.set_size_request(200, -1) obj_tree.set_size_request(200, -1)
columns = [ columns = [
Gtk.TreeViewColumn(title = 'Count', Gtk.TreeViewColumn(title='Count',
cell_renderer = Gtk.CellRendererText(), cell_renderer=Gtk.CellRendererText(),
text = 1, style = 2), text=1, style=2),
Gtk.TreeViewColumn(title = '%', Gtk.TreeViewColumn(title='%',
cell_renderer = Gtk.CellRendererText(), cell_renderer=Gtk.CellRendererText(),
text = 2, style = 2), text=2, style=2),
Gtk.TreeViewColumn(title = 'Size', Gtk.TreeViewColumn(title='Size',
cell_renderer = Gtk.CellRendererText(), cell_renderer=Gtk.CellRendererText(),
text = 3, style = 2), text=3, style=2),
Gtk.TreeViewColumn(title = '%', Gtk.TreeViewColumn(title='%',
cell_renderer = Gtk.CellRendererText(), cell_renderer=Gtk.CellRendererText(),
text = 4, style = 2), text=4, style=2),
Gtk.TreeViewColumn(title = 'Cumulative', Gtk.TreeViewColumn(title='Cumulative',
cell_renderer = Gtk.CellRendererText(), cell_renderer=Gtk.CellRendererText(),
text = 5, style = 2), text=5, style=2),
Gtk.TreeViewColumn(title = 'Max', Gtk.TreeViewColumn(title='Max',
cell_renderer = Gtk.CellRendererText(), cell_renderer=Gtk.CellRendererText(),
text = 6, style = 2), text=6, style=2),
Gtk.TreeViewColumn(title = 'Kind', Gtk.TreeViewColumn(title='Kind',
cell_renderer = Gtk.CellRendererText(), cell_renderer=Gtk.CellRendererText(),
text = 7, style = 2), text=7, style=2),
] ]
first_iter = obj_store.get_iter_first() first_iter = obj_store.get_iter_first()
...@@ -198,8 +201,8 @@ class PyrasiteWindow(Gtk.Window): ...@@ -198,8 +201,8 @@ class PyrasiteWindow(Gtk.Window):
obj_tree.collapse_all() obj_tree.collapse_all()
obj_tree.set_headers_visible(True) obj_tree.set_headers_visible(True)
scrolled_window = Gtk.ScrolledWindow(hadjustment = None, scrolled_window = Gtk.ScrolledWindow(hadjustment=None,
vadjustment = None) vadjustment=None)
scrolled_window.set_policy(Gtk.PolicyType.NEVER, scrolled_window.set_policy(Gtk.PolicyType.NEVER,
Gtk.PolicyType.AUTOMATIC) Gtk.PolicyType.AUTOMATIC)
scrolled_window.add(obj_tree) scrolled_window.add(obj_tree)
...@@ -220,7 +223,8 @@ class PyrasiteWindow(Gtk.Window): ...@@ -220,7 +223,8 @@ class PyrasiteWindow(Gtk.Window):
notebook.append_page(hbox, Gtk.Label.new_with_mnemonic('_Objects')) notebook.append_page(hbox, Gtk.Label.new_with_mnemonic('_Objects'))
(shell_view, shell_widget, shell_buffer) = self.create_text(False, return_view=True) (shell_view, shell_widget, shell_buffer) = \
self.create_text(False, return_view=True)
self.shell_view = shell_view self.shell_view = shell_view
self.shell_buffer = shell_buffer self.shell_buffer = shell_buffer
self.shell_widget = shell_widget self.shell_widget = shell_widget
...@@ -246,25 +250,28 @@ class PyrasiteWindow(Gtk.Window): ...@@ -246,25 +250,28 @@ class PyrasiteWindow(Gtk.Window):
self.notebook = notebook self.notebook = notebook
self.call_graph = Gtk.Image() self.call_graph = Gtk.Image()
scrolled_window = Gtk.ScrolledWindow(hadjustment = None, scrolled_window = Gtk.ScrolledWindow(hadjustment=None,
vadjustment = None) vadjustment=None)
scrolled_window.set_policy(Gtk.PolicyType.ALWAYS, scrolled_window.set_policy(Gtk.PolicyType.ALWAYS,
Gtk.PolicyType.ALWAYS) Gtk.PolicyType.ALWAYS)
scrolled_window.add_with_viewport(self.call_graph) scrolled_window.add_with_viewport(self.call_graph)
notebook.append_page(scrolled_window, Gtk.Label.new_with_mnemonic('_Call Graph')) notebook.append_page(scrolled_window,
Gtk.Label.new_with_mnemonic('_Call Graph'))
self.details_html = '' self.details_html = ''
self.details_view = WebKit.WebView() self.details_view = WebKit.WebView()
self.details_view.load_string(self.details_html, "text/html", "utf-8", '#') self.details_view.load_string(self.details_html, "text/html",
"utf-8", '#')
details_window = Gtk.ScrolledWindow(hadjustment = None, details_window = Gtk.ScrolledWindow(hadjustment=None,
vadjustment = None) vadjustment=None)
details_window.set_policy(Gtk.PolicyType.AUTOMATIC, details_window.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC) Gtk.PolicyType.AUTOMATIC)
details_window.add(self.details_view) details_window.add(self.details_view)
notebook.append_page(details_window, Gtk.Label.new_with_mnemonic('_Details')) notebook.append_page(details_window,
Gtk.Label.new_with_mnemonic('_Details'))
self.show_all() self.show_all()
self.progress.hide() self.progress.hide()
...@@ -286,7 +293,7 @@ class PyrasiteWindow(Gtk.Window): ...@@ -286,7 +293,7 @@ class PyrasiteWindow(Gtk.Window):
insert_mark = self.shell_buffer.get_insert() insert_mark = self.shell_buffer.get_insert()
self.shell_buffer.place_cursor(self.shell_buffer.get_end_iter()) self.shell_buffer.place_cursor(self.shell_buffer.get_end_iter())
self.shell_view.scroll_to_mark(insert_mark , 0.0, True, 0.0, 1.0) self.shell_view.scroll_to_mark(insert_mark, 0.0, True, 0.0, 1.0)
def obj_selection_cb(self, selection, model): def obj_selection_cb(self, selection, model):
sel = selection.get_selected() sel = selection.get_selected()
...@@ -310,7 +317,11 @@ class PyrasiteWindow(Gtk.Window): ...@@ -310,7 +317,11 @@ class PyrasiteWindow(Gtk.Window):
<html><head> <html><head>
<style> <style>
body {font: normal 12px/150%% Arial, Helvetica, sans-serif;} body {font: normal 12px/150%% Arial, Helvetica, sans-serif;}
.grid table { border-collapse: collapse; text-align: left; width: 100%%; } .grid table {
border-collapse: collapse;
text-align: left;
width: 100%%;
}
.grid { .grid {
font: normal 12px/150%% Arial, Helvetica, sans-serif; font: normal 12px/150%% Arial, Helvetica, sans-serif;
background: #fff; overflow: hidden; border: 1px solid #2e3436; background: #fff; overflow: hidden; border: 1px solid #2e3436;
...@@ -318,11 +329,18 @@ class PyrasiteWindow(Gtk.Window): ...@@ -318,11 +329,18 @@ class PyrasiteWindow(Gtk.Window):
} }
.grid table td, .grid table th { padding: 3px 10px; } .grid table td, .grid table th { padding: 3px 10px; }
.grid table thead th { .grid table thead th {
background:-webkit-gradient( linear, left top, left bottom, color-stop(0.05, #888a85), color-stop(1, #555753) ); background:-webkit-gradient(linear, left top, left bottom,
color-stop(0.05, #888a85),
color-stop(1, #555753) );
background-color:#2e3436; color:#FFFFFF; font-size: 15px; background-color:#2e3436; color:#FFFFFF; font-size: 15px;
font-weight: bold; border-left: 1px solid #2e3436; } font-weight: bold; border-left: 1px solid #2e3436; }
.grid table thead th:first-child { border: none; } .grid table thead th:first-child { border: none; }
.grid table tbody td { color: #2e3436; border-left: 1px solid #2e3436;font-size: 12px;font-weight: normal; } .grid table tbody td {
color: #2e3436;
border-left: 1px solid #2e3436;
font-size: 12px;
font-weight: normal;
}
.grid table tbody .alt td { background: #d3d7cf; color: #2e3436; } .grid table tbody .alt td { background: #d3d7cf; color: #2e3436; }
.grid table tbody td:first-child { border: none; } .grid table tbody td:first-child { border: none; }
</style> </style>
...@@ -331,23 +349,29 @@ class PyrasiteWindow(Gtk.Window): ...@@ -331,23 +349,29 @@ class PyrasiteWindow(Gtk.Window):
<h2>%(title)s</h2> <h2>%(title)s</h2>
<div class="grid"> <div class="grid">
<table> <table>
<thead> <thead><tr>
<tr><th width="50%%">CPU: <span id="cpu_details"/></th> <th width="50%%">CPU: <span id="cpu_details"/></th>
<th width="50%%">Memory: <span id="mem_details"/></th></tr> <th width="50%%">Memory: <span id="mem_details"/></th>
</thead> </tr></thead>
<tbody> <tbody>
<tr><td><span id="cpu_graph" class="cpu_graph"></span></td> <tr>
<td><span id="mem_graph" class="mem_graph"></span></td></tr> <td>
<span id="cpu_graph" class="cpu_graph"></span>
</td>
<td>
<span id="mem_graph" class="mem_graph"></span>
</td>
</tr>
</tbody> </tbody>
</table> </table>
</div> </div>
<br/> <br/>
<div class="grid"> <div class="grid">
<table> <table>
<thead> <thead><tr>
<tr><th width="50%%">Read: <span id="read_details"/></th> <th width="50%%">Read: <span id="read_details"/></th>
<th width="50%%">Write: <span id="write_details"/></th></tr> <th width="50%%">Write: <span id="write_details"/></th>
</thead> </tr></thead>
<tbody> <tbody>
<tr><td><span id="read_graph"></span></td> <tr><td><span id="read_graph"></span></td>
<td><span id="write_graph"></span></td></tr> <td><span id="write_graph"></span></td></tr>
...@@ -366,7 +390,7 @@ class PyrasiteWindow(Gtk.Window): ...@@ -366,7 +390,7 @@ class PyrasiteWindow(Gtk.Window):
</table> </table>
</div> </div>
<br/> <br/>
""" % dict(title = proc.title) """ % dict(title=proc.title)
self.info_html += """ self.info_html += """
<div class="grid"> <div class="grid">
...@@ -408,7 +432,8 @@ class PyrasiteWindow(Gtk.Window): ...@@ -408,7 +432,8 @@ class PyrasiteWindow(Gtk.Window):
p.terminal, time.ctime(p.create_time), p.terminal, time.ctime(p.create_time),
p.username, p.uids.real, p.gids.real, p.nice) p.username, p.uids.real, p.gids.real, p.nice)
self.details_view.load_string(self.details_html, "text/html", "utf-8", '#') self.details_view.load_string(self.details_html, "text/html",
"utf-8", '#')
if not self.resource_thread: if not self.resource_thread:
self.resource_thread = ResourceUsagePoller(proc.pid) self.resource_thread = ResourceUsagePoller(proc.pid)
...@@ -419,7 +444,8 @@ class PyrasiteWindow(Gtk.Window): ...@@ -419,7 +444,8 @@ class PyrasiteWindow(Gtk.Window):
self.resource_thread.process = p self.resource_thread.process = p
GObject.timeout_add(100, self.inject_js) GObject.timeout_add(100, self.inject_js)
GObject.timeout_add(int(POLL_INTERVAL * 1000), self.render_resource_usage) GObject.timeout_add(int(POLL_INTERVAL * 1000),
self.render_resource_usage)
def inject_js(self): def inject_js(self):
log.debug("Injecting jQuery") log.debug("Injecting jQuery")
...@@ -432,24 +458,29 @@ class PyrasiteWindow(Gtk.Window): ...@@ -432,24 +458,29 @@ class PyrasiteWindow(Gtk.Window):
sparkline.close() sparkline.close()
def render_resource_usage(self): def render_resource_usage(self):
"""Render our resource usage using jQuery+Sparklines in our WebKit view""" """
Render our resource usage using jQuery+Sparklines in our WebKit view
"""
global cpu_intervals, mem_intervals, cpu_details, mem_details global cpu_intervals, mem_intervals, cpu_details, mem_details
global read_intervals, write_intervals, read_bytes, write_bytes global read_intervals, write_intervals, read_bytes, write_bytes
global open_files, open_connections global open_files, open_connections
script = """ script = """
jQuery('#cpu_graph').sparkline(%s, {'height': 75, 'width': 250, spotRadius: 3, jQuery('#cpu_graph').sparkline(%s, {'height': 75, 'width': 250,
fillColor: '#73d216', lineColor: '#4e9a06'}); spotRadius: 3, fillColor: '#73d216', lineColor: '#4e9a06'});
jQuery('#mem_graph').sparkline(%s, {'height': 75, 'width': 250, jQuery('#mem_graph').sparkline(%s, {'height': 75, 'width': 250,
lineColor: '#5c3566', fillColor: '#75507b', minSpotColor: false, lineColor: '#5c3566', fillColor: '#75507b',
maxSpotColor: false, spotColor: '#f57900', spotRadius: 3}); minSpotColor: false, maxSpotColor: false, spotColor: '#f57900',
spotRadius: 3});
jQuery('#cpu_details').text('%s'); jQuery('#cpu_details').text('%s');
jQuery('#mem_details').text('%s'); jQuery('#mem_details').text('%s');
jQuery('#read_graph').sparkline(%s, {'height': 75, 'width': 250, jQuery('#read_graph').sparkline(%s, {'height': 75, 'width': 250,
lineColor: '#a40000', fillColor: '#cc0000', minSpotColor: false, lineColor: '#a40000', fillColor: '#cc0000',
maxSpotColor: false, spotColor: '#729fcf', spotRadius: 3}); minSpotColor: false, maxSpotColor: false, spotColor: '#729fcf',
spotRadius: 3});
jQuery('#write_graph').sparkline(%s, {'height': 75, 'width': 250, jQuery('#write_graph').sparkline(%s, {'height': 75, 'width': 250,
lineColor: '#ce5c00', fillColor: '#f57900', minSpotColor: false, lineColor: '#ce5c00', fillColor: '#f57900',
maxSpotColor: false, spotColor: '#8ae234', spotRadius: 3}); minSpotColor: false, maxSpotColor: false, spotColor: '#8ae234',
spotRadius: 3});
jQuery('#read_details').text('%s'); jQuery('#read_details').text('%s');
jQuery('#write_details').text('%s'); jQuery('#write_details').text('%s');
""" % (cpu_intervals, mem_intervals, cpu_details, mem_details, """ % (cpu_intervals, mem_intervals, cpu_details, mem_details,
...@@ -473,10 +504,11 @@ class PyrasiteWindow(Gtk.Window): ...@@ -473,10 +504,11 @@ class PyrasiteWindow(Gtk.Window):
for i, open_file in enumerate(open_files)]) for i, open_file in enumerate(open_files)])
if open_connections: if open_connections:
row = '<tr%s><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>'
script += """ script += """
jQuery('#open_connections').html('%s'); jQuery('#open_connections').html('%s');
""" % ''.join(['<tr%s><td>%s</td><td>%s</td><td>%s</td><td>%s</td></tr>' % """ % ''.join([row % (i % 2 and ' class="alt"' or '',
(i % 2 and ' class="alt"' or '', conn['type'], conn['local'], conn['type'], conn['local'],
conn['remote'], conn['status']) conn['remote'], conn['status'])
for i, conn in enumerate(open_connections)]) for i, conn in enumerate(open_connections)])
...@@ -508,10 +540,11 @@ class PyrasiteWindow(Gtk.Window): ...@@ -508,10 +540,11 @@ class PyrasiteWindow(Gtk.Window):
self.proc = proc self.proc = proc
if self.pid and proc.pid != self.pid: if self.pid and proc.pid != self.pid:
global cpu_intervals, mem_intervals, write_intervals, read_intervals global cpu_intervals, mem_intervals, write_intervals, \
global cpu_details, mem_details, read_count, read_bytes, thread_totals read_intervals, cpu_details, mem_details, read_count, \
global write_count, write_bytes, thread_intervals, thread_colors read_bytes, thread_totals, write_count, write_bytes, \
global open_files, open_connections thread_intervals, thread_colors, open_files, \
open_connections
cpu_intervals = [0.0] cpu_intervals = [0.0]
mem_intervals = [] mem_intervals = []
write_intervals = [] write_intervals = []
...@@ -562,7 +595,8 @@ class PyrasiteWindow(Gtk.Window): ...@@ -562,7 +595,8 @@ class PyrasiteWindow(Gtk.Window):
"shutil.move(tmp + '.json', tmp + '.objects')"]) "shutil.move(tmp + '.json', tmp + '.objects')"])
output = proc.cmd(cmd) output = proc.cmd(cmd)
if 'No module named meliae' in output: if 'No module named meliae' in output:
log.error('Error: %s is unable to import `meliae`' % proc.title.strip()) log.error('Error: %s is unable to import `meliae`' %
proc.title.strip())
self.update_progress(0.35) self.update_progress(0.35)
# Clear previous model # Clear previous model
...@@ -570,19 +604,22 @@ class PyrasiteWindow(Gtk.Window): ...@@ -570,19 +604,22 @@ class PyrasiteWindow(Gtk.Window):
self.update_progress(0.4, "Loading object dump") self.update_progress(0.4, "Loading object dump")
try: try:
objects = loader.load('/tmp/%d.objects' % proc.pid, show_prog=False) objects = loader.load('/tmp/%d.objects' % proc.pid,
show_prog=False)
except: except:
log.debug("Falling back to slower meliae object dump loader") log.debug("Falling back to slower meliae object dump loader")
objects = loader.load('/tmp/%d.objects' % proc.pid, show_prog=False, objects = loader.load('/tmp/%d.objects' % proc.pid,
using_json=False) show_prog=False, using_json=False)
objects.compute_referrers() objects.compute_referrers()
self.update_progress(0.45) self.update_progress(0.45)
summary = objects.summarize() summary = objects.summarize()
self.update_progress(0.47) self.update_progress(0.47)
def intify(x): def intify(x):
try: return int(x) try:
except: return x return int(x)
except:
return x
for i, line in enumerate(str(summary).split('\n')): for i, line in enumerate(str(summary).split('\n')):
if i == 0: if i == 0:
...@@ -616,7 +653,8 @@ class PyrasiteWindow(Gtk.Window): ...@@ -616,7 +653,8 @@ class PyrasiteWindow(Gtk.Window):
time.sleep(1) # TODO: make this configurable in the UI time.sleep(1) # TODO: make this configurable in the UI
self.update_progress(0.9, "Generating call stack graph") self.update_progress(0.9, "Generating call stack graph")
image = '/tmp/%d-callgraph.png' % proc.pid image = '/tmp/%d-callgraph.png' % proc.pid
proc.cmd('import pycallgraph; pycallgraph.make_dot_graph("%s")' % image) proc.cmd('import pycallgraph; pycallgraph.make_dot_graph("%s")' %
image)
self.call_graph.set_from_file(image) self.call_graph.set_from_file(image)
def row_activated_cb(self, view, path, col, store): def row_activated_cb(self, view, path, col, store):
...@@ -635,10 +673,8 @@ class PyrasiteWindow(Gtk.Window): ...@@ -635,10 +673,8 @@ class PyrasiteWindow(Gtk.Window):
tree_view.set_size_request(200, -1) tree_view.set_size_request(200, -1)
cell = Gtk.CellRendererText() cell = Gtk.CellRendererText()
column = Gtk.TreeViewColumn(title = 'Processes', column = Gtk.TreeViewColumn(title='Processes', cell_renderer=cell,
cell_renderer = cell, text=0, style=2)
text = 0,
style = 2)
first_iter = tree_store.get_iter_first() first_iter = tree_store.get_iter_first()
if first_iter is not None: if first_iter is not None:
...@@ -651,14 +687,14 @@ class PyrasiteWindow(Gtk.Window): ...@@ -651,14 +687,14 @@ class PyrasiteWindow(Gtk.Window):
tree_view.collapse_all() tree_view.collapse_all()
tree_view.set_headers_visible(False) tree_view.set_headers_visible(False)
scrolled_window = Gtk.ScrolledWindow(hadjustment = None, scrolled_window = Gtk.ScrolledWindow(hadjustment=None,
vadjustment = None) vadjustment=None)
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC) Gtk.PolicyType.AUTOMATIC)
scrolled_window.add(tree_view) scrolled_window.add(tree_view)
label = Gtk.Label(label = 'Processes') label = Gtk.Label(label='Processes')
box = Gtk.Notebook() box = Gtk.Notebook()
box.set_size_request(250, -1) box.set_size_request(250, -1)
...@@ -669,8 +705,8 @@ class PyrasiteWindow(Gtk.Window): ...@@ -669,8 +705,8 @@ class PyrasiteWindow(Gtk.Window):
return box return box
def create_text(self, is_source, return_view=False): def create_text(self, is_source, return_view=False):
scrolled_window = Gtk.ScrolledWindow(hadjustment = None, scrolled_window = Gtk.ScrolledWindow(hadjustment=None,
vadjustment = None) vadjustment=None)
scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC, scrolled_window.set_policy(Gtk.PolicyType.AUTOMATIC,
Gtk.PolicyType.AUTOMATIC) Gtk.PolicyType.AUTOMATIC)
scrolled_window.set_shadow_type(Gtk.ShadowType.IN) scrolled_window.set_shadow_type(Gtk.ShadowType.IN)
...@@ -712,9 +748,9 @@ class PyrasiteWindow(Gtk.Window): ...@@ -712,9 +748,9 @@ class PyrasiteWindow(Gtk.Window):
is_func = False is_func = False
def prepare_iters(): def prepare_iters():
start_iter.set_line(srow-1) start_iter.set_line(srow - 1)
start_iter.set_line_offset(scol) start_iter.set_line_offset(scol)
end_iter.set_line(erow-1) end_iter.set_line(erow - 1)
end_iter.set_line_offset(ecol) end_iter.set_line_offset(ecol)
try: try:
...@@ -726,36 +762,50 @@ class PyrasiteWindow(Gtk.Window): ...@@ -726,36 +762,50 @@ class PyrasiteWindow(Gtk.Window):
if tok_type == tokenize.COMMENT: if tok_type == tokenize.COMMENT:
prepare_iters() prepare_iters()
self.source_buffer.apply_tag_by_name('comment', start_iter, end_iter) self.source_buffer.apply_tag_by_name('comment', start_iter,
end_iter)
elif tok_type == tokenize.NAME: elif tok_type == tokenize.NAME:
if tok_str in keyword.kwlist or tok_str in builtin_constants: if (tok_str in keyword.kwlist or
tok_str in builtin_constants):
prepare_iters() prepare_iters()
self.source_buffer.apply_tag_by_name('keyword', start_iter, end_iter) self.source_buffer.apply_tag_by_name('keyword',
start_iter,
end_iter)
if tok_str == 'def' or tok_str == 'class': if tok_str == 'def' or tok_str == 'class':
# Next token is going to be a function/method/class name # Next token is going to be a
# function/method/class name
is_func = True is_func = True
continue continue
elif tok_str == 'self': elif tok_str == 'self':
prepare_iters() prepare_iters()
self.source_buffer.apply_tag_by_name('italic', start_iter, end_iter) self.source_buffer.apply_tag_by_name('italic',
start_iter,
end_iter)
else: else:
if is_func is True: if is_func is True:
prepare_iters() prepare_iters()
self.source_buffer.apply_tag_by_name('bold', start_iter, end_iter) self.source_buffer.apply_tag_by_name('bold',
start_iter,
end_iter)
elif is_decorator is True: elif is_decorator is True:
prepare_iters() prepare_iters()
self.source_buffer.apply_tag_by_name('decorator', start_iter, end_iter) self.source_buffer.apply_tag_by_name('decorator',
start_iter,
end_iter)
elif tok_type == tokenize.STRING: elif tok_type == tokenize.STRING:
prepare_iters() prepare_iters()
self.source_buffer.apply_tag_by_name('string', start_iter, end_iter) self.source_buffer.apply_tag_by_name('string', start_iter,
end_iter)
elif tok_type == tokenize.NUMBER: elif tok_type == tokenize.NUMBER:
prepare_iters() prepare_iters()
self.source_buffer.apply_tag_by_name('number', start_iter, end_iter) self.source_buffer.apply_tag_by_name('number', start_iter,
end_iter)
elif tok_type == tokenize.OP: elif tok_type == tokenize.OP:
if tok_str == '@': if tok_str == '@':
prepare_iters() prepare_iters()
self.source_buffer.apply_tag_by_name('decorator', start_iter, end_iter) self.source_buffer.apply_tag_by_name('decorator',
start_iter,
end_iter)
# next token is going to be the decorator name # next token is going to be the decorator name
is_decorator = True is_decorator = True
...@@ -789,7 +839,7 @@ class InputStream(object): ...@@ -789,7 +839,7 @@ class InputStream(object):
function isn't used in such a context. (see <python-lib>/tokenize.py) function isn't used in such a context. (see <python-lib>/tokenize.py)
''' '''
def __init__(self, data): def __init__(self, data):
self.__data = [ '%s\n' % x for x in data.splitlines() ] self.__data = ['%s\n' % x for x in data.splitlines()]
self.__lcount = 0 self.__lcount = 0
def readline(self): def readline(self):
...@@ -853,13 +903,15 @@ class ResourceUsagePoller(threading.Thread): ...@@ -853,13 +903,15 @@ class ResourceUsagePoller(threading.Thread):
thread_totals[thread.id] = 0.0 thread_totals[thread.id] = 0.0
if len(thread_intervals[thread.id]) >= INTERVALS: if len(thread_intervals[thread.id]) >= INTERVALS:
thread_intervals[thread.id] = thread_intervals[thread.id][1:INTERVALS] thread_intervals[thread.id] = \
thread_intervals[thread.id][1:INTERVALS]
# FIXME: we should figure out some way to visually # FIXME: we should figure out some way to visually
# distinguish between user and system time. # distinguish between user and system time.
total = thread.system_time + thread.user_time total = thread.system_time + thread.user_time
amount_since = total - thread_totals[thread.id] amount_since = total - thread_totals[thread.id]
thread_intervals[thread.id].append(float('%.2f' % amount_since)) thread_intervals[thread.id].append(
float('%.2f' % amount_since))
thread_totals[thread.id] = total thread_totals[thread.id] = total
# Open connections # Open connections
......
...@@ -33,6 +33,7 @@ from meliae import loader ...@@ -33,6 +33,7 @@ from meliae import loader
from pyrasite.inspect import ObjectInspector from pyrasite.inspect import ObjectInspector
class PyrasiteMemoryViewer(object): class PyrasiteMemoryViewer(object):
palette = [ palette = [
('body', 'black', 'light gray', 'standout'), ('body', 'black', 'light gray', 'standout'),
...@@ -75,8 +76,9 @@ class PyrasiteMemoryViewer(object): ...@@ -75,8 +76,9 @@ class PyrasiteMemoryViewer(object):
if i in (0, 1): if i in (0, 1):
rb = self.create_disabled_radio_button(line) rb = self.create_disabled_radio_button(line)
else: else:
obj = self.summary.summaries[i-2] obj = self.summary.summaries[i - 2]
rb = self.create_radio_button(group, line, obj, self.display_object) rb = self.create_radio_button(group, line, obj,
self.display_object)
buttons.append(rb) buttons.append(rb)
return buttons return buttons
...@@ -107,7 +109,7 @@ class PyrasiteMemoryViewer(object): ...@@ -107,7 +109,7 @@ class PyrasiteMemoryViewer(object):
w = urwid.Frame(header=bt, body=w) w = urwid.Frame(header=bt, body=w)
# Exit message # Exit message
exit = urwid.BigText(('exit'," Quit? "), urwid.Thin6x6Font()) exit = urwid.BigText(('exit', " Quit? "), urwid.Thin6x6Font())
exit = urwid.Overlay(exit, w, 'center', None, 'middle', None) exit = urwid.Overlay(exit, w, 'center', None, 'middle', None)
return w, exit return w, exit
......
...@@ -2,14 +2,15 @@ ...@@ -2,14 +2,15 @@
from __future__ import division from __future__ import division
def humanize_bytes(bytes, precision=1): def humanize_bytes(bytes, precision=1):
"""Return a humanized string representation of a number of bytes.""" """Return a humanized string representation of a number of bytes."""
abbrevs = ( abbrevs = (
(1<<50L, 'PB'), (1 << 50L, 'PB'),
(1<<40L, 'TB'), (1 << 40L, 'TB'),
(1<<30L, 'GB'), (1 << 30L, 'GB'),
(1<<20L, 'MB'), (1 << 20L, 'MB'),
(1<<10L, 'kB'), (1 << 10L, 'kB'),
(1, 'bytes') (1, 'bytes')
) )
if bytes == 1: if bytes == 1:
...@@ -40,6 +41,7 @@ def humanize_bytes(bytes, precision=1): ...@@ -40,6 +41,7 @@ def humanize_bytes(bytes, precision=1):
import logging import logging
import subprocess import subprocess
def run(*args, **kwargs): def run(*args, **kwargs):
"""Run a subprocess. """Run a subprocess.
...@@ -54,8 +56,10 @@ def run(*args, **kwargs): ...@@ -54,8 +56,10 @@ def run(*args, **kwargs):
:param args: arguments to be passed to :class:`subprocess.Popen`. :param args: arguments to be passed to :class:`subprocess.Popen`.
:param kwargs: keyword arguments to be passed to :class:`subprocess.Popen`. :param kwargs: keyword arguments to be passed to :class:`subprocess.Popen`.
:param communicate: if True, call :meth:`subprocess.Popen.communicate` after creating the subprocess. :param communicate: if True, call :meth:`subprocess.Popen.communicate`
:param executable: if present, the path to a program to execute instead of this script. after creating the subprocess.
:param executable: if present, the path to a program to execute instead of
this script.
""" """
_kwargs = { _kwargs = {
"stdin": subprocess.PIPE, "stdin": subprocess.PIPE,
...@@ -82,7 +86,8 @@ def setup_logger(verbose=False): ...@@ -82,7 +86,8 @@ def setup_logger(verbose=False):
NullHandler = logging.NullHandler NullHandler = logging.NullHandler
except AttributeError: except AttributeError:
class NullHandler(logging.Handler): class NullHandler(logging.Handler):
def emit(self, record): pass def emit(self, record):
pass
# Add a do-nothing NullHandler to the module logger to prevent "No handlers # Add a do-nothing NullHandler to the module logger to prevent "No handlers
# could be found" errors. The calling code can still add other, more useful # could be found" errors. The calling code can still add other, more useful
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment