pythonrefactoringpython-importautomated-refactoring

Automatic replacement of indirect imports


I have a small module that defines a function:

# small_file.py
def func():
...

I have a larger module that does a wildcard import of that one:

# giant_file.py
from small_file import *
...

I have hundreds of other files that indirectly import the function via giant_file:

# file1.py
from giant_file import func
...

# file2.py
import giant_file.func
...

# file3.py
from giant_file import func, something_not_in_small_file
...

I would like to automatically change all these other files to import directly from small_file.py. This is to avoid the overhead of loading all of giant_file.py.

My question is this: is there a good way to automatically change all these files to import directly?

My default plan is to write a redbaron-based tool, but I'm hoping there might be a more lightweight approach utilizing an IDE's refactoring capabilities.


Solution

  • I solved this problem by writing a static analysis tool that analyzes my entire codebase and constructs an AST for each file. Using the AST's, the tool traverses imports and attributes each symbol read to an original assignment. It then rewrites all the imports in each file with direct-imports (eliminating unused imports along the way).

    There are some potential pathological cases that the tool misses, such as dynamically constructing strings and then assigning to them via globals(). But it works for most "normal" code.

    I used redbaron for this. If I could do it again, I would use LibCST instead, as redbaron has various bugs and unsupported python language elements, while LibCST appears to be more mature and actively maintained.