importpyfrompy._cmdlineimportpycountlocascountlocfrompy.xmlimportrawfrompypyimportconftestpypydir=py.path.local(conftest.pypydir)defisdocfile(p):return(p.extin('.txt','.rst')orp.basenamein('README','NOTES','LICENSE'))defistestfile(p):ifnotp.check(file=1,ext='.py'):returnFalsepb=p.purebasenameifpb.startswith('test_')orpb.endswith('_test'):returnTrueif'test'in[x.basenameforxinp.parts()[-4:]]:returnTruenotistestfile=lambdax:notistestfile(x)classrelchecker:def__init__(self,rel):self.rel=reldef__call__(self,p):returnp.relto(conftest.pypydir).startswith(self.rel)defisfile(p):returnp.check(file=1)andp.extin('.py','.txt','')defrecpypy(p):ifp.basename[0]=='.':returnFalseifp.basenamein('Pyrex','_cache','unicodedata','pypy-translation-snapshot'):returnFalsereturnTruedefgetpypycounter():filecounter=countloc.FileCounter()root=py.path.local(conftest.pypydir)filecounter.addrecursive(root,isfile,rec=recpypy)returnfilecounterclassCounterModel:def__init__(self,pypycounter):self.counter=pypycounterself.totallines=pypycounter.numlinesself.totalfiles=pypycounter.numfilesself.testlines=pypycounter.getnumlines(istestfile)self.testfiles=pypycounter.getnumfiles(istestfile)self.notestlines=pypycounter.getnumlines(notistestfile)self.notestfiles=pypycounter.getnumfiles(notistestfile)self.doclines=pypycounter.getnumlines(isdocfile)self.docfiles=pypycounter.getnumfiles(isdocfile)## rendering #defrow(*args):returnhtml.tr([html.td(arg)forarginargs])defpercent(x,y):return"%.2f%%"%(x/(y/100.0))defviewlocsummary(model):t=html.table(row("total number of lines",model.totallines,raw("&nbsp;")),row("number of testlines",model.testlines,percent(model.testlines,model.totallines)),row("number of non-testlines",model.notestlines,percent(model.notestlines,model.totallines)),row("total number of files",model.totalfiles,raw("&nbsp;")),row("number of testfiles",model.testfiles,percent(model.testfiles,model.totalfiles)),row("number of non-testfiles",model.notestfiles,percent(model.notestfiles,model.totalfiles)),)ifmodel.docfiles:t.append(row("number of docfiles",model.docfiles,percent(model.docfiles,model.totalfiles)))t.append(row("number of doclines",model.doclines,percent(model.doclines,model.totallines)))returntdefviewloclist(model):t=html.table()d=model.counter.file2numlinespaths=d.items()paths.sort(lambdax,y:-cmp(x[1],y[1]))# sort by numlines forp,numlinesinpaths:ifnumlines<3:continuet.append(row(p.relto(pypydir.dirpath()),numlines))returntdefviewsubdirs(model):t=html.table()forpinpypydir.listdir():ifp.basenamein'_cache .svn'.split():continueifp.check(dir=1):counter=countloc.FileCounter()counter.addrecursive(p,isfile,recpypy)model=CounterModel(counter)t.append(row(html.h2(p.relto(pypydir.dirpath()))))t.append(viewlocsummary(model))t.append(viewloclist(model))returntif__name__=='__main__':iflen(py.std.sys.argv)>=2:target=py.path.local(py.std.sys.argv[1])else:target=py.path.local('index.html')print"writing source statistics to",targetpypycounter=getpypycounter()model=CounterModel(pypycounter)rev=py.path.svnwc(conftest.pypydir).info().revhtml=py.xml.htmldoc=html.html(html.head(html.title("PyPy Statistics %d"%rev),),html.body(html.h2("rev %d PyPy Summary of Files and Lines"%rev),viewlocsummary(model),html.h2("Details on first-level subdirectories"),viewsubdirs(model),html.h3("PyPy Full List Files and Lines"),viewloclist(model),html.p("files with less than 3 lines ignored")))content=doc.unicode(indent=2).encode('utf8')target.write(content)