2

Starting from a script foo.py find all functions that are in use in local source code (i.e not built-in or third party packages), recursively.

EDIT: I do not want to find recursive functions. I want to find all functions that are in use!

e.g. foo.py

import bar

def not_used():
    pass

bar.do_stuff(x,y)

bar.py

import math

def more_stuff(x,y):
    result = math.abs(-x+-y)
    return result

def do_stuff(x,y):
    more_stuff(x,y)

Should return do_stuff & more_stuff

Should ignore not_used & abs

Many thanks

EDIT: Code so far

import dis

py_file = 'foo.py'

with open(py_file) as file:
    source_code = file.read()

compiled = compile(source_code, py_file, "exec")

funcs = []
byte_code = dis.Bytecode(compiled)
instructions = list(reversed([x for x in byte_code]))

for (ix, instruction) in enumerate(instructions):
    if instruction.opname == "CALL_FUNCTION":
        load_func_instr = instructions[ix + instruction.arg + 1]
        funcs.append(load_func_instr.argval)

results = [f'{ix}: {funcname}'for (ix, funcname) in enumerate(reversed(funcs), 1)]
Anonymous
  • 795
  • 1
  • 7
  • 13

1 Answers1

0

You can use Python's ast (abstract syntax tree) module

A short example:

import ast

code = """
import math

def more_stuff(x,y):
    result = math.abs(-x+-y)
    return result

def do_stuff(x,y):
    more_stuff(x,y)
"""

tree = ast.parse(code)

funcs = [x for x in ast.walk(tree) if isinstance(x, ast.FunctionDef)]

print(', '.join(f.name for f in funcs))

prints:

more_stuff, do_stuff

now you can add the tests, you like. For example the SO question
How to find/detect if a build-in function is used in Python AST?
discusses how to detect if a function is being used.

Snow bunting
  • 1,069
  • 8
  • 28
  • Thanks @snow-bunting not really what I'm after, as it would pick-up all the unused functions and it doesn't resolve files that are referenced in imports. But I think a combination of the two approaches could probably work. I was going to write something, but I thought that somebody must've done this before and I hate reinventing the wheel - hence asking on here. – Anonymous Jun 06 '19 at 09:22