Module osbot_utils.helpers.ast.Ast_Load
Expand source code
import ast
from osbot_utils.helpers.Type_Registry import type_registry
from osbot_utils.utils.Files import file_contents, file_exists
from osbot_utils.utils.Functions import python_file
from osbot_utils.helpers.ast.Ast_Node import Ast_Node
#todo: check if this is stll needed since it Ast_Visit does it similar
class Ast_Load(ast.NodeVisitor):
def __init__(self):
self.ast_nodes = {}
self.files_visited = []
def load_file(self, file_path):
if file_exists(file_path):
file_visited = "/".join(file_path.split('/')[-4:])
source_code = file_contents(file_path)
tree = ast.parse(source_code)
self.visit(tree)
self.files_visited.append(file_visited)
return True
return False
def load_files(self, files_paths):
for file_path in files_paths:
self.load_file(file_path)
def load_target(self, file_path):
file = python_file(file_path)
return self.load_file(file)
def add_visited_node(self, node):
ast_node = self.create_ast_node(node)
ast_node_key = ast_node.key() #ast_node.__class__.__name__
if self.ast_nodes.get(ast_node_key) is None:
self.ast_nodes[ast_node_key] = []
self.ast_nodes[ast_node_key].append(ast_node)
def create_ast_node(self, node):
type_key = type(node)
resolved_type = type_registry.resolve(type_key)
if resolved_type:
return resolved_type(node)
return Ast_Node(node)
def generic_visit(self, node):
#print(f'entering {node.__class__.__name__}')
self.add_visited_node(node)
super().generic_visit(node)
def stats(self):
nodes = {}
node_count = 0
for key,list in self.ast_nodes.items():
key_count = len(list)
nodes[key] = key_count
node_count += key_count
stats = { 'files_visited': self.files_visited,
'node_count' : node_count,
'nodes' : nodes }
return stats
Classes
class Ast_Load
-
A node visitor base class that walks the abstract syntax tree and calls a visitor function for every node found. This function may return a value which is forwarded by the
visit
method.This class is meant to be subclassed, with the subclass adding visitor methods.
Per default the visitor functions for the nodes are
'visit_'
+ class name of the node. So aTryFinally
node visit function would bevisit_TryFinally
. This behavior can be changed by overriding thevisit
method. If no visitor function exists for a node (return valueNone
) thegeneric_visit
visitor is used instead.Don't use the
NodeVisitor
if you want to apply changes to nodes during traversing. For this a special visitor exists (NodeTransformer
) that allows modifications.Expand source code
class Ast_Load(ast.NodeVisitor): def __init__(self): self.ast_nodes = {} self.files_visited = [] def load_file(self, file_path): if file_exists(file_path): file_visited = "/".join(file_path.split('/')[-4:]) source_code = file_contents(file_path) tree = ast.parse(source_code) self.visit(tree) self.files_visited.append(file_visited) return True return False def load_files(self, files_paths): for file_path in files_paths: self.load_file(file_path) def load_target(self, file_path): file = python_file(file_path) return self.load_file(file) def add_visited_node(self, node): ast_node = self.create_ast_node(node) ast_node_key = ast_node.key() #ast_node.__class__.__name__ if self.ast_nodes.get(ast_node_key) is None: self.ast_nodes[ast_node_key] = [] self.ast_nodes[ast_node_key].append(ast_node) def create_ast_node(self, node): type_key = type(node) resolved_type = type_registry.resolve(type_key) if resolved_type: return resolved_type(node) return Ast_Node(node) def generic_visit(self, node): #print(f'entering {node.__class__.__name__}') self.add_visited_node(node) super().generic_visit(node) def stats(self): nodes = {} node_count = 0 for key,list in self.ast_nodes.items(): key_count = len(list) nodes[key] = key_count node_count += key_count stats = { 'files_visited': self.files_visited, 'node_count' : node_count, 'nodes' : nodes } return stats
Ancestors
- ast.NodeVisitor
Methods
def add_visited_node(self, node)
-
Expand source code
def add_visited_node(self, node): ast_node = self.create_ast_node(node) ast_node_key = ast_node.key() #ast_node.__class__.__name__ if self.ast_nodes.get(ast_node_key) is None: self.ast_nodes[ast_node_key] = [] self.ast_nodes[ast_node_key].append(ast_node)
def create_ast_node(self, node)
-
Expand source code
def create_ast_node(self, node): type_key = type(node) resolved_type = type_registry.resolve(type_key) if resolved_type: return resolved_type(node) return Ast_Node(node)
def generic_visit(self, node)
-
Called if no explicit visitor function exists for a node.
Expand source code
def generic_visit(self, node): #print(f'entering {node.__class__.__name__}') self.add_visited_node(node) super().generic_visit(node)
def load_file(self, file_path)
-
Expand source code
def load_file(self, file_path): if file_exists(file_path): file_visited = "/".join(file_path.split('/')[-4:]) source_code = file_contents(file_path) tree = ast.parse(source_code) self.visit(tree) self.files_visited.append(file_visited) return True return False
def load_files(self, files_paths)
-
Expand source code
def load_files(self, files_paths): for file_path in files_paths: self.load_file(file_path)
def load_target(self, file_path)
-
Expand source code
def load_target(self, file_path): file = python_file(file_path) return self.load_file(file)
def stats(self)
-
Expand source code
def stats(self): nodes = {} node_count = 0 for key,list in self.ast_nodes.items(): key_count = len(list) nodes[key] = key_count node_count += key_count stats = { 'files_visited': self.files_visited, 'node_count' : node_count, 'nodes' : nodes } return stats