Created
August 29, 2017 21:50
-
-
Save lakshmankumar12/7c7ccb06730600320a67a35849cbda17 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
from __future__ import print_function | |
import re | |
import sys | |
import json | |
import collections | |
import os | |
try: | |
import filetail | |
except ImportError: | |
print("I use the failtail recipe found in https://github.com/ActiveState/code/blob/master/recipes/Python/436477_filetailpy/recipe-436477.py") | |
sys.exit(1) | |
import argparse | |
import tqdm | |
PROGRESS_POINT_PATTERN=r'^((MAKE|PREBUILD).*):\s*(\S+) -> (\S+)' | |
ACE_RPM_PATTERN=r'^--> asn-anap' | |
POP_RPM_PATTERN=r'^mkdir -p .*pop/install' | |
patterns = [ PROGRESS_POINT_PATTERN, ACE_RPM_PATTERN, POP_RPM_PATTERN ] | |
#if elem[0] == 1, then the next tell the match.groups() to use. | |
#elif elem[1] == 0, then use the strings as keys | |
compiled_patterns_keys = [ (1,1,3,4) , (0,"RPM-Finished","RPM-Finished","anap"), (0,"RPM-Finished","RPM-Finished","pop") ] | |
compiled_patterns = [] | |
for i in patterns: | |
compiled_patterns.append(re.compile(i)) | |
BRANCH_INFO_STORE=os.path.expanduser("~/ws/.make_progress_store") | |
def module_factory(): | |
return collections.defaultdict(int) | |
def platform_factory(): | |
return collections.defaultdict(module_factory) | |
def prepare_init_repo(filename): | |
""" Given a make_op filename, it prepares a first time list of progress-points | |
:filename: the make_op file to parse | |
:returns: dict-of-activies -> dict-of-platforms -> dict-of-modules -> count (should be 1!), total-count """ | |
all_activities = collections.defaultdict(platform_factory) | |
total = 0 | |
with open(filename,'r') as fd: | |
for i in fd: | |
for p,key in zip(compiled_patterns,compiled_patterns_keys): | |
m = p.search(i) | |
if m: | |
if key[0]: | |
activity=m.group(key[1]) | |
platform=m.group(key[2]) | |
module=m.group(key[3]) | |
else: | |
activity=key[1] | |
platform=key[2] | |
module=key[3] | |
all_activities[activity][platform][module] += 1 | |
total += 1 | |
break | |
return all_activities,total | |
def psExists(pid): | |
try: | |
os.kill(pid, 0) | |
except OSError: | |
return False | |
else: | |
return True | |
class ProgressChecker: | |
def __init__(self, mp, pid, compareActivity, total): | |
self.makeOp = mp | |
self.make_pid = pid | |
self.toCompare = compareActivity | |
self.ft = filetail.Tail(self.makeOp, max_sleep=5) | |
self.extra_activities = collections.defaultdict(platform_factory) | |
self.totalActivities = total | |
self.completed = 0 | |
def __iter__(self): | |
return self | |
def __next__(self): | |
return self.getNextProgressPoint() | |
def next(self): | |
return self.__next__() | |
def getNextLine(self): | |
while psExists(self.make_pid): | |
line = self.ft.nextline() | |
if line: | |
return line | |
if not psExists(self.make_pid): | |
raise StopIteration | |
# continue looping . The actual sleeping happens inside the filetail library | |
raise StopIteration | |
def getNextProgressPoint(self): | |
while self.completed < self.totalActivities: | |
line = self.getNextLine() | |
for p,key in zip(compiled_patterns,compiled_patterns_keys): | |
m = p.search(line) | |
if m: | |
if key[0]: | |
activity=m.group(key[1]) | |
platform=m.group(key[2]) | |
module=m.group(key[3]) | |
else: | |
activity=key[1] | |
platform=key[2] | |
module=key[3] | |
if activity in self.toCompare: | |
if platform in self.toCompare[activity]: | |
if module in self.toCompare[activity][platform]: | |
self.toCompare[activity][platform][module] -= 1 | |
self.completed += 1 | |
return (self.completed,activity,platform,module) | |
#hmm.. extra activity | |
print("Hey extra: {0:s},{1:s},{2:s}".format(activity,platform,module)) | |
self.extra_activities[activity][platform][module] += 1 | |
break | |
#dont bother about this line | |
raise StopIteration | |
class UnitTest: | |
def __init__(self): | |
pass | |
def test_prepare_init_repo(self): | |
print ("This tests mere generation of init_repo - args: makefile op having progress points") | |
p = prepare_init_repo(sys.argv[1]) | |
js = json.dumps(p,indent=4) | |
print(js) | |
def testFileTailer(self): | |
print ("This tests file tailer library - args, some growing file and a pid to watch") | |
print (" For ex, you can do bash -c 'for i in $(seq 100) ; do echo this is line $i ; sleep 1 ; done' > /tmp/a &\n And supply {0} /tmp/a <pid>".format(sys.argv[0])) | |
ft = filetail.Tail(sys.argv[1]) | |
pid = int(sys.argv[2]) | |
for i in range(1,100): | |
if not psExists(pid): | |
print ("pid doesn't exist anymore") | |
break | |
else: | |
line = ft.nextline() | |
if line: | |
print ("iter:{0:d} got line:{1:s}".format(i,line)) | |
#ut = UnitTest() | |
#ut.test_prepare_init_repo() | |
#ut.testFileTailer() | |
#sys.exit(0) | |
parser = argparse.ArgumentParser() | |
parser.add_argument("-p", "--prepare", help="prepare_init_repo", action="store_true") | |
parser.add_argument("make_op", help="make-op file to follow (or prepare from)") | |
parser.add_argument("branch", help="branch to compare against, (or store for)") | |
parser.add_argument("pid", help="pid of makefile", nargs='?', type=int) | |
parsed_args = parser.parse_args() | |
filename=os.path.join(BRANCH_INFO_STORE,parsed_args.branch) | |
if parsed_args.prepare: | |
all_activities,tot = prepare_init_repo(parsed_args.make_op) | |
if not os.path.exists(BRANCH_INFO_STORE): | |
os.makedirs(BRANCH_INFO_STORE) | |
with open(filename,"w") as fd: | |
a={} | |
a["activities"] = all_activities | |
a["total"] = tot | |
json.dump(a, fd, indent=4) | |
print("Wrote branch {0:s} info to {1:s}. Total of {2:d} activities".format(parsed_args.branch, filename, tot)) | |
sys.exit(0) | |
if not parsed_args.pid: | |
print ("You should supply pid") | |
sys.exit(1) | |
if not os.access(filename,os.F_OK): | |
print ("Couldn't spot file {0:s}. First prepare activities list for branch:{1:s}".format(filename, parsed_args.branch)) | |
with open(filename,"r") as fd: | |
js = json.load(fd) | |
if "total" not in js: | |
print ("Couldn't find total in file:{0:s}".format(filename)) | |
if not psExists(parsed_args.pid): | |
print ("Pid {0:d} doesn't exist".format(parsed_args.pid)) | |
sys.exit(1) | |
pc = ProgressChecker(parsed_args.make_op, parsed_args.pid, js["activities"], js["total"]) | |
last = 0; | |
t = tqdm.tqdm(pc, total=js["total"]) | |
for i in t: | |
last = i[0] | |
t.set_description("{0:10s}-{1:10s}-{2:20s}".format(i[1],i[2],i[3])) | |
if last != js["total"]: | |
print ("Last:{0:d} is less than expected total:{1:d}".format(last,js["total"])) | |
for act in js["activities"]: | |
for plat in js["activities"][act]: | |
for mod in js["activities"][act][plat]: | |
if js["activities"][act][plat][mod] != 0: | |
print(" {0:s},{1:s},{2:s} is not 0, but: {3:d}".format(act,plat,mod,js["activities"][act][plat][mod])) | |
else: | |
print ("Got {0:d} completion points".format(last)) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment