1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2026-03-21 02:22:02 +01:00

Plug together Ui <-> client <-> session <-> plugin + bugfixes

Created a new class LodelSession to handle session datas
Created an automatic wrapper to acces to session handler plugin function throug SessionHandlerPlugin class methods
Bugfixes done for plugins. The plugin type is store in __plugin_type___ and not in __type__
This commit is contained in:
Yann 2016-08-24 15:07:38 +02:00
commit 1453cf49f9
10 changed files with 71 additions and 50 deletions

View file

@ -29,14 +29,14 @@ class LodelSession(object):
#@warning Cause maybe a performance issue ! #@warning Cause maybe a performance issue !
def __token_checker(self): def __token_checker(self):
refcount = sys.getrefcount(self.__token) refcount = sys.getrefcount(self.__token)
if refcount > 1: if self.__token is not None and refcount > 1:
warnings.warn("More than one reference to the session token \ warnings.warn("More than one reference to the session token \
exists !") exists ! (exactly %d)" % refcount)
##@brief Property. Equals True if a session is started else False ##@brief Property. Equals True if a session is started else False
@property @property
def started(self): def started(self):
res = self.__token is None res = self.__token is not None
if res: if res:
self.__token_checker() self.__token_checker()
return res return res
@ -74,7 +74,8 @@ a session is allready started !!!")
def destroy(self): def destroy(self):
if not self.started: if not self.started:
logger.debug("Destroying a session that is not started") logger.debug("Destroying a session that is not started")
SessionHandler.destroy(self.__token) else:
SessionHandler.destroy(self.__token)
self.__token = None self.__token = None
self.__datas = dict() self.__datas = dict()
@ -173,10 +174,8 @@ class Client(object, metaclass = ClientMetaclass):
##@brief Constructor ##@brief Constructor
#@param ui_instance Lodel2Ui child class instance
#@param client_infos mixed : Depends on UI implemetation
#@param session_token mixed : Session token provided by client to interface #@param session_token mixed : Session token provided by client to interface
def __init__(self,ui_instance, client_infos, session_token = None): def __init__(self,session_token = None):
if self.__class__ == Client: if self.__class__ == Client:
raise NotImplementedError("Abstract class") raise NotImplementedError("Abstract class")
logger.debug("New instance of Client child class %s" % logger.debug("New instance of Client child class %s" %
@ -189,14 +188,12 @@ class Client(object, metaclass = ClientMetaclass):
else: else:
#first instanciation, fetching settings #first instanciation, fetching settings
self.fetch_settings() self.fetch_settings()
##@brief Stores instance of UI
self.__ui_instance = ui_instance
##@brief Stores infos for authenticated users (None == anonymous) ##@brief Stores infos for authenticated users (None == anonymous)
self.__user = None self.__user = None
##@brief Stores the session handler ##@brief Stores the session handler
Client._instance = self Client._instance = self
##@brief Stores LodelSession instance ##@brief Stores LodelSession instance
self.__session = LodelSession(token) self.__session = LodelSession(session_token)
logger.debug("New client : %s" % self) logger.debug("New client : %s" % self)
##@brief Attempt to restore a session given a session token ##@brief Attempt to restore a session given a session token
@ -249,6 +246,11 @@ class Client(object, metaclass = ClientMetaclass):
if self.is_anon(): if self.is_anon():
self.fail() #Security logging self.fail() #Security logging
@classmethod
def destroy(cls):
cls._assert_instance()
cls._instance.__session.destroy()
##@brief Test wether a client is anonymous or logged in ##@brief Test wether a client is anonymous or logged in
#@return True if client is anonymous #@return True if client is anonymous
@classmethod @classmethod

View file

@ -17,6 +17,7 @@ class DatasourcePlugin(Plugin):
'key': 'datasource_connectors', 'key': 'datasource_connectors',
'default': None, 'default': None,
'validator': SettingValidator('strip', none_is_valid = False) } 'validator': SettingValidator('strip', none_is_valid = False) }
_type_conf_name = 'datasource'
def __init__(self, name): def __init__(self, name):
super().__init__(name) super().__init__(name)

View file

@ -10,3 +10,5 @@ class Extension(Plugin):
'default': [], 'default': [],
'validator': SettingValidator('list', none_is_valid = False)} 'validator': SettingValidator('list', none_is_valid = False)}
_type_conf_name = 'extension'

View file

@ -12,6 +12,8 @@ class InterfacePlugin(Plugin):
'key': 'interface', 'key': 'interface',
'default': None, 'default': None,
'validator': SettingValidator('strip', none_is_valid = True)} 'validator': SettingValidator('strip', none_is_valid = True)}
_type_conf_name = 'ui'
def __init__(self, name): def __init__(self, name):
if InterfacePlugin._instance is not None: if InterfacePlugin._instance is not None:

View file

@ -43,9 +43,7 @@ DEFAULT_PLUGINS_PATH_LIST = ['./plugins']
MANDATORY_VARNAMES = [PLUGIN_NAME_VARNAME, LOADER_FILENAME_VARNAME, MANDATORY_VARNAMES = [PLUGIN_NAME_VARNAME, LOADER_FILENAME_VARNAME,
PLUGIN_VERSION_VARNAME] PLUGIN_VERSION_VARNAME]
DEFAULT_PLUGIN_TYPE = 'extension' DEFAULT_PLUGIN_TYPE = 'extension' #Value found in lodel/plugin/extensions.py::Extensions._type_conf_name
PLUGINS_TYPES = [DEFAULT_PLUGIN_TYPE, 'datasource', 'session_handler', 'ui']
##@brief Describe and handle version numbers ##@brief Describe and handle version numbers
class PluginVersion(object): class PluginVersion(object):
@ -149,37 +147,38 @@ to generic PluginVersion comparison function : '%s'" % cmp_fun_name)
return {'major': self.major, 'minor': self.minor, return {'major': self.major, 'minor': self.minor,
'revision': self.revision} 'revision': self.revision}
##@brief Stores plugin class registered
__all_ptypes = list()
##@brief Plugin metaclass that allows to "catch" child class ##@brief Plugin metaclass that allows to "catch" child class
#declaration #declaration
# #
#Automatic script registration on child class declaration #Automatic script registration on child class declaration
class MetaPlugType(type): class MetaPlugType(type):
##@brief Dict storing all plugin types
#
#key is the _type_conf_name and value is the class
_all_ptypes = dict()
def __init__(self, name, bases, attrs): def __init__(self, name, bases, attrs):
#Here we can store all child classes of Plugin #Here we can store all child classes of Plugin
super().__init__(name, bases, attrs) super().__init__(name, bases, attrs)
if len(bases) == 1 and bases[0] == object: if len(bases) == 1 and bases[0] == object:
return return
self.__register_types() #Regitering a new plugin type
#list_name= [cls.__name__ for cls in __all_ptypes] MetaPlugType._all_ptypes[self._type_conf_name] = self
#if self.name in list_name:
# return
#else:
# plug_type_register(self)
def __register_types(self): @classmethod
plug_type_register(self) def all_types(cls):
return copy.copy(cls._all_ptypes)
def plug_type_register(cls): @classmethod
__all_ptypes.append(cls) def all_ptype_names(cls):
logger.info("New child class registered : %s" % cls.__name__) return list(cls._all_ptypes.keys())
def all_types():
return copy.copy(__all_ptypes)
@classmethod
def type_from_name(cls, ptype_name):
if ptype_name not in cls._all_ptypes:
raise PluginError("Unknown plugin type '%s'" % ptype_name)
return cls._all_ptypes[ptype_name]
##@brief Handle plugins ##@brief Handle plugins
# #
@ -212,6 +211,11 @@ class Plugin(object, metaclass=MetaPlugType):
#where plugin list is stored #where plugin list is stored
_plist_confspecs = None _plist_confspecs = None
##@brief The name of the plugin type in the confguration
#
#None in abstract classes and implemented by child classes
_type_conf_name = None
##@brief Plugin class constructor ##@brief Plugin class constructor
# #
# Called by setting in early stage of lodel2 boot sequence using classmethod # Called by setting in early stage of lodel2 boot sequence using classmethod
@ -290,7 +294,8 @@ class Plugin(object, metaclass=MetaPlugType):
except AttributeError: except AttributeError:
self.__type = DEFAULT_PLUGIN_TYPE self.__type = DEFAULT_PLUGIN_TYPE
self.__type = str(self.__type).lower() self.__type = str(self.__type).lower()
if self.__type not in PLUGINS_TYPES: if self.__type not in MetaPlugType.all_ptype_names():
print("FUCK : ", MetaPlugType.all_ptype_names())
raise PluginError("Unknown plugin type '%s'" % self.__type) raise PluginError("Unknown plugin type '%s'" % self.__type)
# Load plugin name from init file (just for checking) # Load plugin name from init file (just for checking)
try: try:
@ -427,6 +432,9 @@ name differ from the one found in plugin's init file"
logger.debug("Plugin '%s' loaded" % self.name) logger.debug("Plugin '%s' loaded" % self.name)
self.loaded = True self.loaded = True
##@brief Returns the loader module
#
#Accessor for the __loader__ python module
def loader_module(self): def loader_module(self):
if not self.loaded: if not self.loaded:
raise RuntimeError("Plugin %s not loaded yet."%self.name) raise RuntimeError("Plugin %s not loaded yet."%self.name)
@ -535,10 +543,10 @@ file : '%s'. Running discover again..." % DISCOVER_CACHE_FILENAME)
raise PluginError("No plugin named %s found" % plugin_name) raise PluginError("No plugin named %s found" % plugin_name)
pinfos = pdcache['plugins'][plugin_name] pinfos = pdcache['plugins'][plugin_name]
ptype = pinfos['type'] ptype = pinfos['type']
if ptype == 'datasource': if ptype not in MetaPlugType.all_ptype_names():
pcls = DatasourcePlugin raise PluginError("Unknown plugin type '%s'" % ptype)
else: pcls = MetaPlugType.type_from_name(ptype)
pcls = cls print("\n\n\nINSTANCIATING : ", pcls, " from name : ", ptype)
plugin = pcls(plugin_name) plugin = pcls(plugin_name)
cls._plugin_instances[plugin_name] = plugin cls._plugin_instances[plugin_name] = plugin
logger.debug("Plugin %s available." % plugin) logger.debug("Plugin %s available." % plugin)
@ -655,7 +663,7 @@ file : '%s'. Running discover again..." % DISCOVER_CACHE_FILENAME)
##@brief Return a list of child Class Plugin ##@brief Return a list of child Class Plugin
@classmethod @classmethod
def plugin_types(cls): def plugin_types(cls):
return all_types() return MetaPlugType.all_types()
##@brief Attempt to open and load plugin discover cache ##@brief Attempt to open and load plugin discover cache
#@return discover cache #@return discover cache

View file

@ -17,14 +17,19 @@ class SessionPluginWrapper(MetaPlugType):
def __init__(self, name, bases, attrs): def __init__(self, name, bases, attrs):
super().__init__(name, bases, attrs) super().__init__(name, bases, attrs)
self._instance = None
##@brief Handles wrapper between class method and plugin loader functions ##@brief Handles wrapper between class method and plugin loader functions
def __get_attribute__(self, name): def __getattribute__(self, name):
if name in SessionPluginWrapper._Actions: instance = super().__getattribute__('_instance')
if name in SessionPluginWrapper._ACTIONS:
if instance is None:
raise PluginError("Trying to access to SessionHandler \
functions, but no session handler initialized")
return getattr( return getattr(
self._instance.loader_module(), instance.loader_module(),
SessionPluginWrapper._Actions[name]) SessionPluginWrapper._ACTIONS[name])
return super().__get_attribute__(name) return super().__getattribute__(name)
##@page lodel2_plugins Lodel2 plugins system ##@page lodel2_plugins Lodel2 plugins system
@ -45,10 +50,12 @@ class SessionHandlerPlugin(Plugin, metaclass=SessionPluginWrapper):
'key': 'session_handler', 'key': 'session_handler',
'default': None, 'default': None,
'validator': SettingValidator('string', none_is_valid=False)} 'validator': SettingValidator('string', none_is_valid=False)}
_type_conf_name = 'session_handler'
def __init__(self, plugin_name): def __init__(self, plugin_name):
if self._instance is None: if self._instance is None:
super(Plugin, self).__init__(plugin_name) super().__init__(plugin_name)
self._instance = self self.__class__._instance = self
else: else:
raise RuntimeError("A SessionHandler Plugin is already plug") raise RuntimeError("A SessionHandler Plugin is already plug")

View file

@ -135,7 +135,7 @@ class Settings(object, metaclass=MetaSettings):
lodel2_specs = LODEL2_CONF_SPECS lodel2_specs = LODEL2_CONF_SPECS
loader = SettingsLoader(self.__conf_dir) loader = SettingsLoader(self.__conf_dir)
plugin_list = [] plugin_list = []
for ptype in Plugin.plugin_types(): for ptype_name,ptype in Plugin.plugin_types().items():
pls = ptype.plist_confspecs() pls = ptype.plist_confspecs()
lodel2_specs = confspec_append(lodel2_specs, **pls) lodel2_specs = confspec_append(lodel2_specs, **pls)
cur_list = loader.getoption( cur_list = loader.getoption(
@ -161,7 +161,6 @@ class Settings(object, metaclass=MetaSettings):
# Starting the Plugins class # Starting the Plugins class
logger.debug("Starting lodel.plugin.Plugin class") logger.debug("Starting lodel.plugin.Plugin class")
print("DEBUG : plugin list : ", plugin_list)
Plugin.start(plugin_list) Plugin.start(plugin_list)
# Fetching conf specs from plugins # Fetching conf specs from plugins
specs = [lodel2_specs] specs = [lodel2_specs]

View file

@ -2,7 +2,7 @@ from lodel.settings.validator import SettingValidator
__plugin_name__ = 'ram_session' __plugin_name__ = 'ram_session'
__version__ = [0,0,1] __version__ = [0,0,1]
__type__ = 'session_handler' __plugin_type__ = 'session_handler'
__loader__ = 'main.py' __loader__ = 'main.py'
__author__ = "Lodel2 dev team" __author__ = "Lodel2 dev team"
__fullname__ = "RAM Session Store Plugin" __fullname__ = "RAM Session Store Plugin"

View file

@ -1,5 +1,5 @@
__plugin_name__ = 'webui' __plugin_name__ = 'webui'
__version__ = '0.0.1' __version__ = '0.0.1'
__type__ = 'ui' __plugin_type__ = 'ui'
__loader__ = 'main.py' __loader__ = 'main.py'
__confspec__ = 'confspec.py' __confspec__ = 'confspec.py'

View file

@ -2,10 +2,10 @@ from lodel.auth.client import Client
class WebUiClient(Client): class WebUiClient(Client):
def __init__(self, ip, user_agent): def __init__(self, ip, user_agent, session_token = None):
self.__ip = ip self.__ip = ip
self.__user_agent = user_agent self.__user_agent = user_agent
super().__init__() super().__init__(session_token = session_token)
def __str__(self): def __str__(self):
return "%s (%s)" % (self.__ip, self.__user_agent) return "%s (%s)" % (self.__ip, self.__user_agent)