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 a TryFinally node visit function would be visit_TryFinally. This behavior can be changed by overriding the visit method. If no visitor function exists for a node (return value None) the generic_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