Skip to content

Instantly share code, notes, and snippets.

@christabor
Last active January 7, 2021 23:45
Embed
What would you like to do?
A quick script to analyze python package code structure
"""Generate a report about the meta information of a pckage.
This includes its children modules,
functions, classes, arg/kwarg count, etc.
"""
import ast
import inspect
import os
import pkgutil
import sys
from pprint import pprint as ppr
EXCLUDED = ['__pycache__']
BADDIRS = [
'libsass', 'node_modules',
'lib', '.git', 'writeContents', '__pycache__',
'.scrapy', '.github',
]
def is_valid_dirpath(dirpath):
return all([
substr not in dirpath for substr in EXCLUDED
])
def is_baddir(dirname):
return len(dirname) == 0 or dirname in BADDIRS
def top_level_functions(body):
return (f for f in body if isinstance(f, ast.FunctionDef))
def parse_ast(filename):
with open(filename, 'r') as file:
return ast.parse(file.read(), filename=filename)
def get_report():
"""Build out a report of functions and their args."""
files = []
badfiles = ['__init__.py']
report = {}
for (dirpath, dirname, filenames) in os.walk(sys.argv[1]):
if is_valid_dirpath(dirpath) and not is_baddir(dirname):
files.extend([
('{}/{}/'.format(os.getcwd(), dirpath), f)
for f in filenames
if f.endswith('.py') and
f not in badfiles
])
for name in files:
name = name[0] + name[1]
obj = parse_ast(name)
subreport = {}
for el in top_level_functions(obj.body):
subreport[el.name] = dict(
args=len(el.args.args) if el.args.args is not None else 0,
kwargs=len(el.args.kwarg) if el.args.kwarg is not None else 0,
)
report[name] = subreport
return report
f = get_report()
ppr(f)
@dbrnz
Copy link

dbrnz commented Nov 16, 2020

Thanks for this!

In order to get it to work I had to change the lines:

    for (dirpath, dirname, filenames) in os.walk(sys.argv[1]):
        if is_valid_dirpath(dirpath) and not is_baddir(dirname):
            files.extend([

to:

    for (dirpath, dirnames, filenames) in os.walk(sys.argv[1]):
        if is_valid_dirpath(dirpath):
            for n, dirname in enumerate(dirnames):
                if is_baddir(dirname):
                    del dirnames[n]
            files.extend([

@christabor
Copy link
Author

Awesome, thanks for adding this. Glad it was helpful!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment