PyCodeWriter
PyCodeWriter is a Python utility class designed to interpret and
manipulate Python code in the form of Abstract Syntax Tree (AST) nodes.
It enables creating, updating, deleting, and writing Python modules
using AST, providing an interface for programmatically generating and
modifying Python source code.
Overview
PyCodeWriter uses the Python built-in ast module and
interactions with py_module_loader, an instance of the
PyModuleLoader class, for operations. This class consists of methods
that map to typical file operations. Unique exceptions labeled
ModuleNotFoundError, StatementNotFoundError and
InvalidArgumentsError, each provide specific error handling for
common pitfalls.
Example Usage
from automata.singletons.dependency_factory import DependencyFactory
from automata.code_writers.py.py_code_writer import PyCodeWriter
from ast import parse
# Create an instance of PyCodeWriter
dep_factory = DependencyFactory()
py_writer = dep_factory.create_py_writer()
# Create a new module with a function "foo"
source_code = """
def foo():
return 'Hello, world!'
"""
py_writer.create_new_module('sample_module', parse(source_code), do_write=True)
# Update the module "foo" function logic
source_code_update = """
def foo():
return 'Hello from updated world!'
"""
py_writer.upsert_to_module(
parse(source_code),
parse(source_code_update)
)
In this example, the method create_new_module was used to create a
new Python module sample_module with a function foo. Following
this, the function foo’s logic was updated with
upsert_to_module to change its return string.
Limitations
PyCodeWriter has strong dependencies on the project and file
structure. It requires the modules to be setup in a specific way. As
such, it may not work accurately if the project structure is not aligned
with its expectations.
Also, PyCodeWriter heavily relies on the ast module. It would
not be effective for changes not supported by the ast module.
In certain operations, such as delete_from_module, there’s a need
for deletion items to already exist in the module, else it will throw an
error. Care must be taken to ensure the preconditions for each operation
are met before execution.
Follow-up Questions:
Are there safeguards for handling common user errors such as attempting to modify a non-existent file or node?
How can this class be extended/modified to support different file and module structures?