Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5a60e47c12 | ||
|
|
355915e9c1 | ||
|
|
0da36439a6 | ||
|
|
3d402db2c2 | ||
|
|
de04b2b3b9 | ||
|
|
fffba77497 | ||
|
|
28057dddd6 | ||
|
|
d46e3b9859 | ||
|
|
c67c5e3e28 | ||
|
|
a45d975617 |
@@ -15,9 +15,7 @@ classifiers = [
|
|||||||
"License :: OSI Approved :: CeCILL-C",
|
"License :: OSI Approved :: CeCILL-C",
|
||||||
"Operating System :: OS Independent",
|
"Operating System :: OS Independent",
|
||||||
]
|
]
|
||||||
dependencies = [
|
dependencies = [ ]
|
||||||
"systemd-python",
|
|
||||||
]
|
|
||||||
dynamic = ["version"]
|
dynamic = ["version"]
|
||||||
|
|
||||||
[project.urls]
|
[project.urls]
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import sys
|
|||||||
import traceback
|
import traceback
|
||||||
from configparser import ConfigParser
|
from configparser import ConfigParser
|
||||||
import logging
|
import logging
|
||||||
from systemd import journal
|
|
||||||
import inspect
|
import inspect
|
||||||
from enum import Enum, auto
|
from enum import Enum, auto
|
||||||
import signal
|
import signal
|
||||||
@@ -13,7 +12,7 @@ from importlib import import_module
|
|||||||
from threading import Thread, Lock
|
from threading import Thread, Lock
|
||||||
|
|
||||||
import inspect
|
import inspect
|
||||||
from threading import Thread
|
from threading import Thread, Event
|
||||||
|
|
||||||
|
|
||||||
def is_number(s):
|
def is_number(s):
|
||||||
@@ -49,6 +48,8 @@ class AppEngineException(Exception):
|
|||||||
def __init__(self, error: AEErrs, mesg=None) -> None:
|
def __init__(self, error: AEErrs, mesg=None) -> None:
|
||||||
if mesg is None:
|
if mesg is None:
|
||||||
self.mesg = str(error)
|
self.mesg = str(error)
|
||||||
|
else:
|
||||||
|
self.mesg = mesg
|
||||||
super().__init__(self.mesg)
|
super().__init__(self.mesg)
|
||||||
self.value = error.value
|
self.value = error.value
|
||||||
|
|
||||||
@@ -63,6 +64,7 @@ class Commands(Thread):
|
|||||||
self.cmods = {}
|
self.cmods = {}
|
||||||
self.config = config
|
self.config = config
|
||||||
self.log = log
|
self.log = log
|
||||||
|
self.stop_all_event = None
|
||||||
self.stopped = False
|
self.stopped = False
|
||||||
self.nickname = None
|
self.nickname = None
|
||||||
if not (self.config is None):
|
if not (self.config is None):
|
||||||
@@ -105,8 +107,8 @@ class Commands(Thread):
|
|||||||
self.stopped = True
|
self.stopped = True
|
||||||
|
|
||||||
def free(self):
|
def free(self):
|
||||||
""" Virtual method used to clean resources for threaded Commands
|
""" Virtual method used to clean resources for all Commands
|
||||||
when they are stopped.
|
when the application is exited.
|
||||||
"""
|
"""
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@@ -174,7 +176,28 @@ class Commands(Thread):
|
|||||||
|
|
||||||
if module == "":
|
if module == "":
|
||||||
if method == 'help':
|
if method == 'help':
|
||||||
return self.list_modules()
|
# No argument was given to the help function
|
||||||
|
if len(args) == 0 and len(kwargs) == 0:
|
||||||
|
msg = "Type 'help <module>' to have the list of module's functions.\n"
|
||||||
|
msg += "Type 'help <module>.<function>' to documentation of a specific function.\n"
|
||||||
|
success, ret = self.list_modules()
|
||||||
|
return success, msg + ret
|
||||||
|
else:
|
||||||
|
# 1 argument has been provided
|
||||||
|
if len(args) > 0:
|
||||||
|
arg = args[0]
|
||||||
|
else:
|
||||||
|
arg = list(kwargs.keys())[0]
|
||||||
|
spl = arg.split(".", 1)
|
||||||
|
|
||||||
|
# help <module>
|
||||||
|
if len(spl) == 1:
|
||||||
|
module = arg
|
||||||
|
# help <module>.<method>
|
||||||
|
else:
|
||||||
|
module = spl[0]
|
||||||
|
args = [spl[1]]
|
||||||
|
kwargs = {}
|
||||||
else:
|
else:
|
||||||
module = self.defmod
|
module = self.defmod
|
||||||
|
|
||||||
@@ -187,6 +210,10 @@ class Commands(Thread):
|
|||||||
|
|
||||||
return self.cmods[module]._execute_command(method, *args, **kwargs)
|
return self.cmods[module]._execute_command(method, *args, **kwargs)
|
||||||
|
|
||||||
|
def stop_all(self):
|
||||||
|
if self.stop_all_event is not None:
|
||||||
|
self.stop_all_event.set()
|
||||||
|
|
||||||
def cmd_help(self, *args, **kwargs):
|
def cmd_help(self, *args, **kwargs):
|
||||||
"""Help of module commands.
|
"""Help of module commands.
|
||||||
Params:
|
Params:
|
||||||
@@ -218,7 +245,7 @@ class Commands(Thread):
|
|||||||
|
|
||||||
|
|
||||||
class CommandsLoader:
|
class CommandsLoader:
|
||||||
def __init__(self, config: ConfigParser, log: logging.Handler, modpath: str):
|
def __init__(self, stop_event: Event, config: ConfigParser, log: logging.Handler, modpath: str):
|
||||||
self.config = config
|
self.config = config
|
||||||
self.modpath = modpath
|
self.modpath = modpath
|
||||||
sys.path.append(os.path.join(modpath))
|
sys.path.append(os.path.join(modpath))
|
||||||
@@ -232,6 +259,7 @@ class CommandsLoader:
|
|||||||
self.prefcmds = prefcmds
|
self.prefcmds = prefcmds
|
||||||
self.log = log
|
self.log = log
|
||||||
self.lock = Lock()
|
self.lock = Lock()
|
||||||
|
self.stop_event = stop_event
|
||||||
self._load_commands()
|
self._load_commands()
|
||||||
self._set_cmods()
|
self._set_cmods()
|
||||||
|
|
||||||
@@ -273,9 +301,14 @@ class CommandsLoader:
|
|||||||
obj = None
|
obj = None
|
||||||
for n, c in members:
|
for n, c in members:
|
||||||
if issubclass(c, Commands) and (n != "Commands"):
|
if issubclass(c, Commands) and (n != "Commands"):
|
||||||
obj = c(conf, self.log)
|
try:
|
||||||
|
obj = c(conf, self.log)
|
||||||
|
except:
|
||||||
|
self.log.error(f"The object '{c.__name__}' could not be instantiated.")
|
||||||
|
continue
|
||||||
obj.log = self.log
|
obj.log = self.log
|
||||||
obj.lock = self.lock
|
obj.lock = self.lock
|
||||||
|
obj.stop_all_event = self.stop_event
|
||||||
break
|
break
|
||||||
|
|
||||||
return obj
|
return obj
|
||||||
@@ -287,9 +320,15 @@ class CommandsLoader:
|
|||||||
def _load_dependencies(self):
|
def _load_dependencies(self):
|
||||||
for k, v in self.cmods.items():
|
for k, v in self.cmods.items():
|
||||||
if hasattr(v, "dependencies"):
|
if hasattr(v, "dependencies"):
|
||||||
for p in v.dependencies:
|
deps = v.dependencies
|
||||||
if p in self.cmods.keys():
|
# dependencies can be a list or dictionary
|
||||||
setattr(v, p, self.cmods[p])
|
if isinstance(v.dependencies, list):
|
||||||
|
deps = {}
|
||||||
|
for d in v.dependencies:
|
||||||
|
deps[d] = d
|
||||||
|
for p, pv in deps.items():
|
||||||
|
if pv in self.cmods.keys():
|
||||||
|
setattr(v, p, self.cmods[pv])
|
||||||
else:
|
else:
|
||||||
self.log.error(
|
self.log.error(
|
||||||
'Dependency "{}" of module "{}" could not be satisfied'.format(
|
'Dependency "{}" of module "{}" could not be satisfied'.format(
|
||||||
@@ -315,8 +354,7 @@ class CommandsLoader:
|
|||||||
|
|
||||||
def free(self):
|
def free(self):
|
||||||
for k, v in self.cmods.items():
|
for k, v in self.cmods.items():
|
||||||
if v.threaded:
|
v.free()
|
||||||
v.free()
|
|
||||||
|
|
||||||
|
|
||||||
class AppEngine:
|
class AppEngine:
|
||||||
@@ -338,6 +376,10 @@ class AppEngine:
|
|||||||
self.log.setLevel(logging.DEBUG)
|
self.log.setLevel(logging.DEBUG)
|
||||||
else:
|
else:
|
||||||
self.log.setLevel(logging.WARNING)
|
self.log.setLevel(logging.WARNING)
|
||||||
|
# Mechanism to stop the application
|
||||||
|
self.stop_event = Event()
|
||||||
|
self.stop_thread = Thread(target=self.wait_stop, args=(self.stop_event,))
|
||||||
|
self.stop_thread.start()
|
||||||
|
|
||||||
def signal_handler(self, sig, frame):
|
def signal_handler(self, sig, frame):
|
||||||
print("\nExiting.")
|
print("\nExiting.")
|
||||||
@@ -364,17 +406,17 @@ class AppEngine:
|
|||||||
if is_writeable:
|
if is_writeable:
|
||||||
self.log.addHandler(logging.FileHandler(fname))
|
self.log.addHandler(logging.FileHandler(fname))
|
||||||
else:
|
else:
|
||||||
self.log.addHandler(journal.JournalHandler())
|
|
||||||
self.log.error('No write permissions: "{}"'.format(fname))
|
self.log.error('No write permissions: "{}"'.format(fname))
|
||||||
|
|
||||||
else:
|
|
||||||
self.log.addHandler(journal.JournalHandler())
|
|
||||||
|
|
||||||
def exec(self, modpath: str = ""):
|
def exec(self, modpath: str = ""):
|
||||||
self.cl = CommandsLoader(self.conf, self.log, modpath)
|
self.cl = CommandsLoader(self.stop_event, self.conf, self.log, modpath)
|
||||||
self.cl.start()
|
self.cl.start()
|
||||||
self.cl.join()
|
self.cl.join()
|
||||||
self.cl.free()
|
self.cl.free()
|
||||||
|
|
||||||
|
def wait_stop(self, evnt):
|
||||||
|
evnt.wait()
|
||||||
|
self.cl.stop()
|
||||||
|
|
||||||
def stop(self):
|
def stop(self):
|
||||||
self.cl.stop()
|
self.stop_event.set()
|
||||||
Reference in New Issue
Block a user