if self trace print(dirpath'override or extend me def visitfile(selffilepath)called for each file self fcount + override or extend me if self trace print(self fcount'=>'filepathclass searchvisitor(filevisitor)""search files at and below startdir for stringsubclassredefine visitmatchextension listscandidate as neededsubclasses can use testexts to specify file types to search (but can also redefine candidate to use mimetypes for text contentsee ahead""skipexts [testexts [txt'py'pyw'html' ' '#skipexts [gif'jpg'pyc' ' 'exe'search these exts or skip these exts def __init__(selfsearchkeytrace= )filevisitor __init__(selfsearchkeytraceself scount def reset(self)self scount on independent walks def candidate(selffname)ext os path splitext(fname)[ if self testextsreturn ext in self testexts elsereturn ext not in self skipexts redef for mimetypes def visitfile(selffname)filevisitor visitfile(selffnameif not self candidate(fname)if self trace print('skipping'fnameelsetext open(fnameread(if self context in textself visitmatch(fnametextself scount + test for match def visitmatch(selffnametext)print('% has % (fnameself context)process match override me lower if __name__ ='__main__'self-test logic dolist dosearch =do list and search donext when next test added def selftest(testmask) complete system programs in test list or not in skip list 'rbif undecodable or text find(!-