Skip to content

Instantly share code, notes, and snippets.

@ychaouche
Created June 17, 2012 12:40
Show Gist options
  • Save ychaouche/2944446 to your computer and use it in GitHub Desktop.
Save ychaouche/2944446 to your computer and use it in GitHub Desktop.
Tahar code inspector -> tells you if your python code is readable or not.
Hello,
Tahar is a little program (named after Inspecteur Tahar, a famous algerian movie character) that helps you keep your code minimal and clean. It warns you if one of your functions or methods code is longer than MAX_LENGTH lines (you can change the value of this macro in the begining of tahar's source code. Default is 25, this is the french EPITA/EPITECH's school standard for C functions).
You don'thave to copy tahar.py (or naive_tahar.py at the time of this writing) in the directory containing the modules you want to scan. You can just pass a dirctory or a list of python files with full access path.
Tahar should print something like this :
<execution trace>
chaouche@karabeela ~/PROG $ python naive_tahar.py autoguess.py hang.py
your app has 13 functions and methods in 2 classes across 2 modules
__init__ : 5
difficulty_menu : 19
enter_game : 25
exit : 4
get_random_word : 4
run : 7
welcome_screen : 7
__init__ : 6
fill : 3
filled : 2
auto_guess : 13
base_guess : 11
get_order : 3
All your code should be readable.
chaouche@karabeela ~/PROG $
</execution trace>
If all your functions are less than MAX_LENGTH lines, then Tahar tells you that your code should be readable.
This is a work in progress (still in alpha) and needs your code reviews.
import inspect
import sys
import os
import dircache
MAX_LENGTH = 25
def pretty_box(string):
print "##"+"#"*(len(string))+"##"
print "#",string,"#"
print "##"+"#"*(len(string))+"##"
def get_module(file_name):
# if it's a directory return all modules and submodules recursively
if os.path.isdir(file_name):
files = dircache.listdir(file_name)
return [get_module(one_file) for one_file in files]
if ".py" in file_name:
exploded_path = file_name.split(".py")[0].split(os.sep)
module_name = exploded_path[-1]
package = os.sep.join(exploded_path[:-1])
## if package:
## sys.path.append(package)
## print "added %s to the path -filename was %s- " % (package,file_name)
if package not in sys.path:
sys.path.append(package)
print "added '%s' to the path" % (package)
print "importing module",module_name
return __import__(module_name)
def main():
modules_names = [modulename.split(".py")[0] for modulename in sys.argv[1:]]
if not modules_names:
print "usage : %s source1.py [source2.py] ... " % sys.argv[0]
exit(0)
modules = [get_module(file_name) for file_name in sys.argv[1:]]
functions = map(lambda x:x[1],reduce(lambda x,y:x+y,[inspect.getmembers(module,inspect.isfunction) for module in modules]))
classes = map(lambda x:x[1],reduce(lambda x,y:x+y,[inspect.getmembers(module,inspect.isclass) for module in modules],[]))
methods = map(lambda x:x[1],reduce(lambda x,y:x+y,[inspect.getmembers(klass,inspect.ismethod) for klass in classes],[]))
loc = 0
all_ok = True
padding = max([len(function.func_name) for function in methods+functions])
pretty_box("Functions and methods lengths (in lines of code)")
for method in methods+functions :
lines = inspect.getsourcelines(method)
code_length = len(filter(lambda line:line.strip() and line.strip()[0] not in "#",inspect.getsourcelines(method)[0]))
loc += code_length
if code_length > MAX_LENGTH :
print "warning : method %s has %s lines" % (method.func_name, code_length)
all_ok = False
else:
print method.func_name.ljust(padding),":",code_length
if all_ok :
print "All your code should be readable. -max length is configured to %s-" % MAX_LENGTH
print "your app has %s lines of code, %s functions and methods in %s classes across %s modules" % (loc,len(methods)+len(functions),len(classes),len(modules))
if __name__ == "__main__":
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment