I am having python files with the import statements which I would like to replace into the actual code placed in the foo.py.
For instance, with the in
file:
from foo import Barbar = Bar()
print bar
I would like to out
file below:
# source of Bar class.bar = Bar()
print bar
How can I perform such imports replacement ?
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_locationsimport astorclass FromImportTransformer(NodeTransformer):""" General from imports transformer. """def visit_ImportFrom(self, node):new_node = self.get_sources(node)# Replace node.fix_missing_locations(node)return nodedef get_sources(self, node):""" Accepts importFrom node and build new ast tree from the sources described in import. """raise NotImplementeddef 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 excsources = astor.to_source(root, indent_with=' ' * 4, add_line_information=False)return processed_sourcespath_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.