Source code for hal.meta.attributes

# -*- coding: utf-8 -*-

"""Finds attributes of classes and functions in files"""

import ast
import os

from hal.files.models.files import Document
from hal.files.models.system import get_folder_name, is_file, \
    is_folder

MODULE_SEP = "."


[docs]class ModuleFile: """File attributes""" def __init__(self, path, root_package): """ :param path: Path of file to parse """ self.path = path self.package = self._find_package(root_package) self.tree = self._parse() def _parse(self): """Parses file contents :return: Tree hierarchy of file """ with open(self.path, "rt") as reader: return ast.parse(reader.read(), filename=self.path) def _find_package(self, root_package): """Finds package name of file :param root_package: root package :return: package name """ package = self.path.replace(root_package, "") if package.endswith(".py"): package = package[:-3] package = package.replace(os.path.sep, MODULE_SEP) root_package = get_folder_name(root_package) package = root_package + package # add root return package
[docs] def get_tree(self): """Finds tree hierarchy of file :return: Tree """ return ModuleTree(self.tree, root_package=self.package)
[docs]class ModuleTree: """Hierarchy""" def __init__(self, tree, root_package): """ :param tree: ast tree """ self.tree = tree self.package = root_package def _get_instances(self, instance): """Finds all instances of instance in tree :param instance: type of object :return: list of objects in tree of same instance """ return [ x for x in self.tree.body if isinstance(x, instance) ]
[docs] def get_classes(self): """Finds classes in file :return: list of top-level classes """ instances = self._get_instances(ast.ClassDef) instances = [ PyClass(instance, self.package) for instance in instances ] return instances
[docs] def get_functions(self): """Finds top-level functions in file :return: list of top-level functions """ instances = self._get_instances(ast.FunctionDef) instances = [ PyFunction(instance, self.package) for instance in instances ] return instances
[docs] def get_name(self): """Finds name of tree :return: name """ return self.tree.name
[docs]class ModuleTreeObject(ModuleTree): """Object of Python tree""" def __init__(self, tree, root_package): super().__init__(tree, root_package) self.full_package = self.package + MODULE_SEP + self.get_name()
[docs]class PyClass(ModuleTreeObject): """Python parsed class"""
[docs] def get_functions(self, include_meta=False): """Finds top-level functions in file :param include_meta: whether include meta functions like (__init__) :return: list of top-level functions """ instances = self._get_instances(ast.FunctionDef) instances = [ PyFunction(instance, self.full_package) # fix package name for instance in instances ] if not include_meta: instances = [ instance # fix package name for instance in instances if not instance.get_name().startswith("__") ] return instances
[docs]class PyFunction(ModuleTreeObject): """Python parsed method"""
def _get_modules(path): """Finds modules in folder recursively :param path: directory :return: list of modules """ lst = [] folder_contents = os.listdir(path) is_python_module = "__init__.py" in folder_contents if is_python_module: for file in folder_contents: full_path = os.path.join(path, file) if is_file(full_path): lst.append(full_path) if is_folder(full_path): lst += _get_modules(full_path) # recurse in folder return list(set(lst))
[docs]def get_modules(folder, include_meta=False): """Finds modules (recursively) in folder :param folder: root folder :param include_meta: whether include meta files like (__init__ or __version__) :return: list of modules """ files = [ file for file in _get_modules(folder) if is_file(file) # just files ] if not include_meta: files = [ file for file in files if not Document(file).name.startswith("__") ] return files
[docs]def get_class_name(obj): """Finds name of class of object :param obj: object :return: Name of class """ return str(obj.__class__.__name__)
[docs]def get_method_name(func): """Finds name of method :param func: method :return: Name of method """ return str(func.__name__)