I suggest you to use the ast.NodeTransformer in order to accomplish such import replacement.
AST provides way to interact with the python code as with the trees of the Python abstract syntax grammar.
The ast.NodeTransformer can be used to traverse through your code and identifying ImportFrom node ( the code parsed with ast is represented as the tree of nodes). After identifying ImportFrom node you can replace it with group of nodes which correspond to the source code of the Bar
class, which lead to your goal.
Please see code below which describes approach described below:
from ast import NodeTransformer, parse, fix_missing_locations
import astor
class FromImportTransformer(NodeTransformer):
""" General from imports transformer. """
def visit_ImportFrom(self, node):
new_node = self.get_sources(node)
# Replace node.
fix_missing_locations(node)
return node
def get_sources(self, node):
""" Accepts importFrom node and build new ast tree from the sources described in import. """
raise NotImplemented
def transform_imports(self, source_file):
with open(source_file) as original_sources:
sources = original_sources.read()
root = parse(sources, source_file)
try:
root = FromImportTransformer().visit(root)
except Exception as exc:
raise exc
sources = astor.to_source(root, indent_with=' ' * 4, add_line_information=False)
return processed_sources
path_to_in_sources = '/tmp/in.py'
path_to_out_sources = '/tmp/out.py'
processed_sources = transform_imports(path_to_in_sources)
with open(path_to_out_sources, 'wb+') as out:
out.write(processed_sources)
NOTE 1: I suggest you to use the exec in order to compile sources with correct globals and locals dict.
NOTE 2: Take into account that you will need to handle nested imports ( if foo file stores imports you wish to replace to).
NOTE 3: I've used astor to convert code from ast tree into the python code.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…