Skip to content

Commit

Permalink
PID lookup works
Browse files Browse the repository at this point in the history
  • Loading branch information
zendorx committed Feb 9, 2017
1 parent 08501d4 commit c3b8e5b
Show file tree
Hide file tree
Showing 3 changed files with 156 additions and 39 deletions.
37 changes: 33 additions & 4 deletions gui.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import getpass
import os
import time
from Tkinter import *
import re


from smcore import *

Expand All @@ -10,9 +11,14 @@ class AppGui():
def update_status_bar(self):
text = ""


if self.last_saved_file:
text += "Saved: " + self.last_saved_file + " "

if self.pid_lookup_enabled:
text += "pid: %s" % (self.app.get_current_pid()) + " "


total = len(self.app.get_lines())

showed = self._filtered_count if self._filtered_count else total
Expand Down Expand Up @@ -68,6 +74,9 @@ def command_text_changed(self, ev):
self.redraw_lines()
self.ready_to_finish = False

def on_lines_changed(self):
self.redraw_lines()

def on_new_lines(self, compiled_lines):
self.textbox.configure(state=NORMAL)
for line in compiled_lines:
Expand Down Expand Up @@ -119,6 +128,23 @@ def do_clean(self):
self.app.clear()
self.redraw_lines()

def set_pid_lookup(self, string):
self.pid_lookup = string
self.set_pid_lookup_enabled(True)
self.app.set_pid_lookup_string(string)
self.app.set_pid_filter_enabled(True)


def set_pid_lookup_enabled(self, value):
if not self.pid_lookup and value:
error("Cannot set pid lookup, pid lookup string is empty")
return

self.pid_lookup_enabled = value

def set_pid_mask(self, string):
self.app.set_pid_mask(re.compile(string))

def __init__(self, app):
self._filtered_count = 0
self.app = app
Expand All @@ -130,8 +156,11 @@ def __init__(self, app):
self.set_current_folder("{t} {uid}.log")
self.clean_command = "adb logcat -c"
self.ready_to_finish = False
self.pid_lookup = ""
self.pid = None
self.pid_lookup_enabled = False

self.root.update_idletasks() # Update "requested size" from geometry manager
self.root.update_idletasks()
w = 800
h = 900
x = (self.root.winfo_screenwidth() - w) / 2
Expand All @@ -158,7 +187,6 @@ def __init__(self, app):
textvariable=self.sv_status_bar)
self.status_bar.pack(side="bottom", fill="both")

# TOP
self.label_filter = Label(self.panelFrame, text="Filter", bg="grey")
self.label_filter.grid(row=0)

Expand All @@ -168,7 +196,6 @@ def __init__(self, app):
textvariable=self.sv_filter, width=45)
self.textFilter.grid(row=0, column=1, padx=5, pady=10)

#
self.scrollbar = Scrollbar(self.textFrame)
self.scrollbar['command'] = self.textbox.yview
self.scrollbar.pack(side='right', fill='y')
Expand All @@ -177,4 +204,6 @@ def __init__(self, app):
self.root.bind("<Escape>", self.on_esc_pressed)
self.sv_filter.trace("w",
lambda name, index, mode, sv=self.sv_filter: self.command_text_changed(self.sv_filter))

app.set_new_lines_callback(self.on_new_lines)
app.set_lines_changed_callback(self.on_lines_changed)
27 changes: 16 additions & 11 deletions smartlog.pyw
Original file line number Diff line number Diff line change
Expand Up @@ -29,16 +29,17 @@ parser = argparse.ArgumentParser(prog=app_name, # todo: move to description
parser.add_argument("-cd", default="",
help="specifies directory where log files will be saved")

parser.add_argument("--command_execute", default="adb logcat", action='store_const', const=True, help="executes clean command on app close.")

parser.add_argument("--exit_clean", default=False, action='store_const', const=True, help="executes clean command on app close.")
parser.add_argument("--start_clean", default=False, action='store_const', const=True, help="executes clean command on startup.")
parser.add_argument("--command_clean", default="adb logcat -c", action='store_const', const=True, help="specifies clean command.")

parser.add_argument("--pid_lookup", default=False, action='store_const', const=True, help="specifies string for looking process id.")
parser.add_argument("--pid_mask", default=".*\((.*?)\).*", action='store_const', const=True, help="specifies regex to searching pid in a text line.")
parser.add_argument("--command_execute", default="adb logcat", action='store_const', const=True,
help="executes clean command on app close.")

parser.add_argument("--exit_clean", default=False, action='store_const', const=True,
help="executes clean command on app close.")
parser.add_argument("--start_clean", default=False, action='store_const', const=True,
help="executes clean command on startup.")
parser.add_argument("--command_clean", default="adb logcat -c", help="specifies clean command.")

parser.add_argument("--pid_lookup", default="", help="specifies string for looking process id.")
parser.add_argument("--pid_mask", default="\((.*?)\)", help="specifies regex to searching pid in a text line.")

# parser.add_argument("-ec", default=exit_commands,
# help="commands that will executed on exit splited by ';' e.g: 'w;q' will write file and open explorer. To see more commands type :h")
Expand Down Expand Up @@ -74,11 +75,12 @@ parser.add_argument("--pid_mask", default=".*\((.*?)\).*", action='store_const',

_args = parser.parse_args()

#IF DEBUG
_args.command_execute = "netstat -a"
# IF DEBUG
# _args.command_execute = "netstat -a"

file_name = default_file_name


def fix_current_dir(value):
cd = value
if cd == ".":
Expand All @@ -103,11 +105,14 @@ gui.set_clean_command(_args.command_clean)
if _args.start_clean:
app.clear()


gui.set_current_file_name(file_name)
gui.set_current_folder(current_dir)
gui.update_title("Smartlog - '" + _args.command_execute + "'")

if _args.pid_lookup:
gui.set_pid_mask(_args.pid_mask)
gui.set_pid_lookup(_args.pid_lookup)

app.set_command_exec(_args.command_execute)
app.start_reading()

Expand Down
131 changes: 107 additions & 24 deletions smcore.py
Original file line number Diff line number Diff line change
@@ -1,22 +1,24 @@
# defaults
import os
import subprocess
from Queue import Queue, Empty
from threading import Thread, Event
import threading
from Queue import Queue, Empty
from logging import getLogger
import os

from threading import Thread, Event

L = getLogger(__name__)


def check_class(var, clazz):
if not isinstance(var, clazz):
err = "wrong type " + str(type(var)) + ", looking for " + str(clazz)
raise Exception(err)


def error(text):
print "\nError: ", str(text), "\n\n"


def log(text):
return
print str(text)
Expand Down Expand Up @@ -46,24 +48,26 @@ def tag_normal(): return "__normal_tag__"

@staticmethod
def get_tag(tag_shortcut):
tags = { "e" : default.tag_error(), "w" : default.tag_warning(), "d" : default.tag_debug(), "l" : default.tag_lookup(), "n" : default.tag_normal()}
tags = { "e": default.tag_error(), "w": default.tag_warning(), "d": default.tag_debug(),
"l": default.tag_lookup(), "n": default.tag_normal() }
return tags[tag_shortcut]


def read_output(command, queue):
try:
while 1:
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True, universal_newlines=True)
p = subprocess.Popen(command, stdout=subprocess.PIPE, shell=True)
# print "subprocess id : %d" % (p.pid, )
for line in iter(p.stdout.readline, b''):
log("queue: " + line)
queue.put(line.strip().decode('866').encode("utf-8"))
queue.put(line.strip())
if (threading.current_thread().is_stopped()):
raise KeyboardInterrupt("")
except KeyboardInterrupt:
print "Finished"
exit()
except Exception:
except Exception as e:
print e
error("Failed to execute command: '%s' " % command)
queue.put(default.interrupt())

Expand All @@ -81,13 +85,16 @@ def is_stopped(self):
return self._stop.isSet()



class CompiledLine():
def __init__(self, index, text, tag):
def __init__(self, index, text, tag, pid):
self.index = index
self.tag = tag
self.original = text
self.text = text.lower()
self.pid = pid

def get_pid(self):
return self.pid

def get_original(self):
return self.original
Expand All @@ -99,14 +106,19 @@ def get_tag(self):
return self.tag

def get(self):
return self.original
return self.text

def can_show(self, filter_words):
def can_show(self, filter_words, pid):
for word in filter_words:
if not word in self.text:
return False

if pid and pid != self.pid:
return False

return True


class Reader():
def __init__(self, command):
self.queue = Queue()
Expand All @@ -125,7 +137,7 @@ def update(self):
lines = []
try:
while 1:
line = self.queue.get_nowait()
line = self.queue.get_nowait().strip()
if len(line):
log(line)
lines.append(line)
Expand All @@ -136,11 +148,24 @@ def update(self):
log("lines:" + str(lines))
return lines

def get_pid(line, regex_pid):
result = regex_pid.findall(line)
if len(result):
print result[0]
return result[0].lower().strip()
return None

def compile_line(line, index, regex_pid):
tag = default.get_tag("n")
pid = None

if regex_pid:
pid = get_pid(line, regex_pid)

def compile_lines(lines, total):
return [CompiledLine(total + index, x, default.get_tag("n")) for index, x in enumerate(lines)]
return CompiledLine(index, line, tag, pid)

def compile_lines(lines, total, regex_pid):
return [compile_line(x, total + index, regex_pid) for index, x in enumerate(lines)]


class SMBuffer():
Expand All @@ -163,13 +188,61 @@ def save_to_file(self, name):
pass



class SmartlogApp():
def __init__(self):
self.buffer = SMBuffer()
self.filter = []
self.command = default.command()
self.new_line_callback = None
self.lines_changed_callback = None
self.pid_mask = None
self.pid_filter_enabled = False
self.pid = None

def get_current_pid(self):
return self.pid

def update_pid(self, lines):
if not self.pid_mask:
return False
if not self.pid_filter_enabled:
return False

for line in lines[::-1]:
text = line.get()
pid = line.get_pid()
update = False
if text.find(self.pid_lookup_string) != -1:
if pid and self.pid != pid:
update = True

if update:
self.pid = pid
if self.lines_changed_callback:
self.lines_changed_callback()
return True
return False

def get_lines_count(self):
return len(self.buffer.get_lines())

def set_pid_mask(self, mask):
self.pid_mask = mask

def set_pid_lookup_string(self, value):
self.pid_lookup_string = value.lower()

def set_pid_filter_enabled(self, value):
self.pid_filter_enabled = value
self.pid = None
if value:
self.update_pid(self.buffer.get_lines())

def do_recompile(self):
new_buffer = SMBuffer()
new_buffer.add(compile_lines([x.get_original() for x in self.buffer.get_lines()], self.get_lines_count(), self.pid_mask))
self.buffer = new_buffer
self.update_pid(self.buffer.get_lines())

def clear(self, command):
self.buffer.clear()
Expand Down Expand Up @@ -199,14 +272,17 @@ def set_filter(self, words):
for word in words.split(" "):
self.filter.append(word.lower().strip())

def set_lines_changed_callback(self, callback):
self.lines_changed_callback = callback

def set_new_lines_callback(self, callback):
self.new_line_callback = callback

def do_filter(self, lines):
return [x for x in lines if x.can_show(self.filter)]
return [x for x in lines if x.can_show(self.filter, self.pid)]

def get_filtered_buffer(self):#return filtered CompiledLine list
if self.filter:
def get_filtered_buffer(self):
if self.filter or self.pid:
return self.do_filter(self.buffer.get_lines())
else:
return self.buffer.get_lines()
Expand All @@ -215,11 +291,18 @@ def update(self):
lines = self.reader.update()

if len(lines):
compiled_lines = compile_lines(lines, len(self.buffer.get_lines()))
compiled_lines = compile_lines(lines, self.get_lines_count(), self.pid_mask)
self.buffer.add(compiled_lines)

if self.new_line_callback:
if self.filter:
self.new_line_callback(self.do_filter(compiled_lines))
updated = self.update_pid(compiled_lines)
if not updated:
if self.filter or self.pid:
new_lines = self.do_filter(compiled_lines)
else:
self.new_line_callback(compiled_lines)
new_lines = compiled_lines

if self.new_line_callback:
self.new_line_callback(new_lines)



0 comments on commit c3b8e5b

Please sign in to comment.