forked from richibrics/IoTuring
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
SettingsClassManager and SettingsManager
- Loading branch information
Showing
17 changed files
with
309 additions
and
267 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,107 +1,109 @@ | ||
from __future__ import annotations | ||
|
||
import os | ||
from pathlib import Path | ||
from os import path | ||
import importlib.util | ||
import importlib.machinery | ||
import sys | ||
import inspect | ||
from IoTuring.Logger.LogObject import LogObject | ||
|
||
# from IoTuring.ClassManager import consts | ||
|
||
# This is a parent class | ||
|
||
# Implement subclasses in this way: | ||
|
||
# def __init__(self): | ||
# ClassManager.__init__(self) | ||
# self.baseClass = Entity : Select the class to find | ||
# self.GetModulesFilename(consts.ENTITIES_PATH) : Select path where it should look for classes and add all classes to found list | ||
|
||
# This class is used to find and load classes without importing them | ||
# The important this is that the class is inside a folder that exactly the same name of the Class and of the file (obviously not talking about extensions) | ||
|
||
|
||
class ClassManager(LogObject): | ||
def __init__(self): | ||
self.modulesFilename = [] | ||
module_path = sys.modules[self.__class__.__module__].__file__ | ||
if not module_path: | ||
raise Exception("Error getting path: " + str(module_path)) | ||
|
||
# Set up these class variables in subclasses: | ||
classesRelativePath = None # Change in subclasses | ||
|
||
|
||
def __init__(self) -> None: | ||
|
||
classmanager_file_path = sys.modules[self.__class__.__module__].__file__ | ||
if not classmanager_file_path: | ||
raise Exception("Error getting path: " + | ||
str(classmanager_file_path)) | ||
|
||
self.rootPath = Path(classmanager_file_path).parents[1] | ||
|
||
# Store loaded classes here: | ||
self.loadedClasses = [] | ||
|
||
# Collect paths | ||
self.moduleFilePaths = self.GetModuleFilePaths() | ||
|
||
|
||
def GetModuleFilePaths(self) -> list: | ||
if not self.classesRelativePath: | ||
raise Exception("Path to deployments not defined") | ||
|
||
classesRootPath = self.rootPath.joinpath(self.classesRelativePath) | ||
|
||
if not classesRootPath.exists: | ||
raise Exception(f"Path does not exist: {classesRootPath}") | ||
|
||
self.Log(self.LOG_DEVELOPMENT, | ||
f'Looking for python files in "{classesRootPath}"...') | ||
|
||
python_files = classesRootPath.rglob("*.py") | ||
|
||
# TO check if a py files is in a folder !!!! with the same name !!! (same without extension) | ||
filepaths = [f for f in python_files if f.stem == f.parent.stem] | ||
|
||
self.Log(self.LOG_DEVELOPMENT, | ||
f"Found {str(len(filepaths))} modules files") | ||
|
||
return filepaths | ||
|
||
def GetClassFromName(self, wantedName: str) -> type | None: | ||
|
||
# Check from already loaded classes: | ||
module_class = next( | ||
(m for m in self.loadedClasses if m.__name__ == wantedName), None) | ||
|
||
if module_class: | ||
return module_class | ||
|
||
modulePath = next( | ||
(m for m in self.moduleFilePaths if m.stem == wantedName), None) | ||
|
||
if modulePath: | ||
|
||
loadedModule = self.LoadModule(modulePath) | ||
loadedClass = self.GetClassFromModule(loadedModule) | ||
self.loadedClasses.append(loadedClass) | ||
return loadedClass | ||
|
||
else: | ||
self.mainPath = path.dirname(path.abspath(module_path)) | ||
# THIS MUST BE IMPLEMENTED IN SUBCLASSES, IS THE CLASS I WANT TO SEARCH !!!! | ||
self.baseClass = None | ||
|
||
def GetClassFromName(self, wantedName) -> type | None: | ||
# From name, load the correct module and extract the class | ||
for module in self.modulesFilename: # Search the module file | ||
moduleName = self.ModuleNameFromPath(module) | ||
# Check if the module name matches the given name | ||
if wantedName == moduleName: | ||
# Load the module | ||
loadedModule = self.LoadModule(module) | ||
# Now get the class | ||
return self.GetClassFromModule(loadedModule) | ||
return None | ||
|
||
def LoadModule(self, path): # Get module and load it from the path | ||
return None | ||
|
||
def LoadModule(self, module_path: Path): # Get module and load it from the path | ||
try: | ||
loader = importlib.machinery.SourceFileLoader( | ||
self.ModuleNameFromPath(path), path) | ||
module_path.stem, str(module_path)) | ||
spec = importlib.util.spec_from_loader(loader.name, loader) | ||
|
||
if not spec: | ||
raise Exception("Spec not found") | ||
|
||
module = importlib.util.module_from_spec(spec) | ||
loader.exec_module(module) | ||
moduleName = os.path.split(path)[1][:-3] | ||
sys.modules[moduleName] = module | ||
sys.modules[module_path.stem] = module | ||
return module | ||
except Exception as e: | ||
self.Log(self.LOG_ERROR, "Error while loading module " + | ||
path + ": " + str(e)) | ||
self.Log(self.LOG_ERROR, | ||
f"Error while loading module {module_path.stem}: {str(e)}") | ||
|
||
# From the module passed, I search for a Class that has className=moduleName | ||
def GetClassFromModule(self, module): | ||
for name, obj in inspect.getmembers(module): | ||
if inspect.isclass(obj): | ||
if(name == module.__name__): | ||
if (name == module.__name__): | ||
return obj | ||
raise Exception(f"No class found: {module.__name__}") | ||
|
||
# List files in the _path directory and get only files in subfolders | ||
def GetModulesFilename(self, _path): | ||
classesRootPath = path.join(self.mainPath, _path) | ||
if os.path.exists(classesRootPath): | ||
self.Log(self.LOG_DEVELOPMENT, | ||
"Looking for python files in \"" + _path + os.sep + "\"...") | ||
result = list(Path(classesRootPath).rglob("*.py")) | ||
entities = [] | ||
for file in result: | ||
filename = str(file) | ||
# TO check if a py files is in a folder !!!! with the same name !!! (same without extension) | ||
pathList = filename.split(os.sep) | ||
if len(pathList) >= 2: | ||
if pathList[len(pathList)-1][:-3] == pathList[len(pathList)-2]: | ||
entities.append(filename) | ||
|
||
self.modulesFilename = self.modulesFilename + entities | ||
self.Log(self.LOG_DEVELOPMENT, "Found " + | ||
str(len(entities)) + " modules files") | ||
|
||
def ModuleNameFromPath(self, path): | ||
classname = os.path.split(path) | ||
return classname[1][:-3] | ||
|
||
def ListAvailableClassesNames(self) -> list: | ||
res = [] | ||
for py in self.modulesFilename: | ||
res.append(path.basename(py).split(".py")[0]) | ||
return res | ||
|
||
def ListAvailableClasses(self) -> list: | ||
return [self.GetClassFromName(n) for n in self.ListAvailableClassesNames()] | ||
|
||
return [self.GetClassFromName(f.stem) for f in self.moduleFilePaths] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,12 +1,7 @@ | ||
from IoTuring.ClassManager.ClassManager import ClassManager | ||
from IoTuring.ClassManager import consts | ||
from IoTuring.Entity.Entity import Entity | ||
|
||
|
||
# Class to load Entities from the Entitties dir and get them from name | ||
# Class to load Entities from the Entitties dir | ||
class EntityClassManager(ClassManager): | ||
def __init__(self): | ||
ClassManager.__init__(self) | ||
self.baseClass = Entity | ||
self.GetModulesFilename(consts.ENTITIES_PATH) | ||
# self.GetModulesFilename(consts.CUSTOM_ENTITIES_PATH) # TODO Decide if I'll use customs | ||
classesRelativePath = consts.ENTITIES_PATH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
from IoTuring.ClassManager.ClassManager import ClassManager | ||
from IoTuring.ClassManager import consts | ||
|
||
|
||
# Class to load Entities from the Entitties dir | ||
class SettingsClassManager(ClassManager): | ||
|
||
classesRelativePath = consts.SETTINGS_PATH | ||
|
||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,11 +1,9 @@ | ||
from IoTuring.ClassManager.ClassManager import ClassManager | ||
from IoTuring.ClassManager import consts | ||
from IoTuring.Warehouse.Warehouse import Warehouse | ||
|
||
|
||
# Class to load Entities from the Entitties dir and get them from name | ||
# Class to load Warehouses from the Warehouses dir | ||
|
||
class WarehouseClassManager(ClassManager): | ||
def __init__(self): | ||
ClassManager.__init__(self) | ||
self.baseClass = Warehouse | ||
self.GetModulesFilename(consts.WAREHOUSES_PATH) | ||
|
||
classesRelativePath = consts.WAREHOUSES_PATH |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,3 @@ | ||
ENTITIES_PATH = "../Entity/Deployments/" | ||
WAREHOUSES_PATH = "../Warehouse/Deployments/" | ||
ENTITIES_PATH = "Entity/Deployments" | ||
WAREHOUSES_PATH = "Warehouse/Deployments" | ||
SETTINGS_PATH = "Settings/Deployments" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.