"""
@brief Base class for all loaders that load dictionaries of python fragments
The PythonLoader class inherits from the DictLoader base class and is intended
to be inherited by all loader classes that read dictionaries in the file system
made up of multiple python file fragments.
This Class only adds helper functions and thus does not overwrite any methods in
in the base DictLoader class. Because of this, all dictionaries returned from
this class will be empty.
@date Created July 3, 2018
@author R. Joseph Paetz
@bug No known bugs
"""
import glob
import importlib
import os
import sys
from fprime_gds.common.data_types import exceptions
# Custom Python Modules
from . import dict_loader
[docs]class PythonLoader(dict_loader.DictLoader):
"""Class to help load python file based dictionaries"""
[docs] def read_dict(self, path, use_superpkg=False):
"""
Reads all python modules at the given path and constructs a dict list
This function assumes that path is a directory containing many python
module files. Each module file has several fields with associated
values. This function reads each file and constructs a dictionary using
the fields and their values. These dictionaries are then compiled into
a list that is returned.
Args:
path: File Path to a folder containing python modules to load
user_superpkg: [Default=False] When true, modules will be imported
using both the package and superpackage qualifiers
(from A.B import C instead of from B import C). This
allows multiple dictionaries with the same package
name to be imported. This is esspecially important
when trying to import dictionaries from multiple
deployments.
Returns:
A list of dictionaries. Each dictionary represents one loaded module
and for keys has the names of the fields in the file and for values
has the values of those fields.
"""
modules = self.importmodules(path, use_superpkg)
module_dicts = []
for module in modules:
# Create a dictionary for this module's fields
mod_dict = dict()
for field in dir(module):
# Verify it is not a hidden field (doesn't start with "__")
if field.find("__") != 0:
mod_dict[field] = getattr(module, field)
module_dicts.append(mod_dict)
return module_dicts
[docs] def importmodules(self, path, use_superpkg):
"""
Imports all modules in the given directory.
Args:
path: File Path to a folder containing python modules to load
user_superpkg: When true, modules will be imported
using both the package and superpackage qualifiers
(from A.B import C instead of from B import C). This
allows multiple dictionaries with the same package
name to be imported. This is esspecially important
when trying to import dictionaries from multiple
deployments.
Returns:
A list of module objects of all the newly imported modules
"""
# Verify path is a directory
if not os.path.isdir(path):
raise exceptions.GseControllerUndefinedDirectoryException(path)
# Compute package and superpackage names
(superpkg_path, pkg) = os.path.split(path)
(rest_of_path, superpkg) = os.path.split(superpkg_path)
# Make sure the directory we are importing from is in the python path
if use_superpkg:
sys.path.append(rest_of_path)
else:
sys.path.append(superpkg_path)
# Make sure serializeable directory is imported
sys.path.append(superpkg_path + os.sep + "serializable")
# Compute a list of all files to import
all_files = glob.glob(path + os.sep + "*.py")
module_files = []
for py_file in all_files:
(file_path, file_name) = os.path.split(py_file)
if file_name != "__init__.py":
module_files.append(file_name)
# Import modules
module_list = []
for mf in module_files:
# Strip off .py from name by splitting at '.' and taking the first
# string
mod_name = mf.split(".")[0]
if use_superpkg:
import_name = "{}.{}.{}".format(superpkg, pkg, mod_name)
else:
import_name = "{}.{}".format(pkg, mod_name)
m = importlib.import_module(import_name)
module_list.append(m)
return module_list