1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2026-08-04 11:28:37 +02:00

Datasources plugins enhancement and loading bugfixes

- now we have a LodelHook to trigger migration handlers loading
- datasources initialization in dyncode is now trigger by a hook (lodel2_plugin_loaded)
- datasources loading by dyncode is better
This commit is contained in:
Yann 2016-06-10 14:04:06 +02:00
commit 9a82936fbf
7 changed files with 40 additions and 75 deletions

View file

@ -15,6 +15,7 @@ def dyncode_from_em(model):
# Header # Header
imports = """from lodel.leapi.leobject import LeObject imports = """from lodel.leapi.leobject import LeObject
from lodel.leapi.datahandlers.base_classes import DataField from lodel.leapi.datahandlers.base_classes import DataField
from lodel.plugin.hooks import LodelHook
""" """
for module in modules: for module in modules:
imports += "import %s\n" % module imports += "import %s\n" % module
@ -27,14 +28,27 @@ from lodel.leapi.datahandlers.base_classes import DataField
{classes} {classes}
{bootstrap_instr} {bootstrap_instr}
dynclasses = {class_list} dynclasses = {class_list}
{init_hook}
""".format( """.format(
imports = imports, imports = imports,
classes = cls_code, classes = cls_code,
bootstrap_instr = bootstrap_instr, bootstrap_instr = bootstrap_instr,
class_list = '[' + (', '.join([cls for cls in class_list]))+']', class_list = '[' + (', '.join([cls for cls in class_list]))+']',
init_hook = datasource_init_hook(),
) )
return res_code return res_code
##@brief Produce the source code of the LodelHook that initialize datasources
#in dyncode
#@return str
def datasource_init_hook():
return """
@LodelHook("lodel2_plugins_loaded")
def lodel2_dyncode_datasources_init(self, caller, payload):
for cls in dynclasses:
cls._init_datasources()
"""
##@brief return A list of EmClass sorted by dependencies ##@brief return A list of EmClass sorted by dependencies
# #
# The first elts in the list depends on nothing, etc. # The first elts in the list depends on nothing, etc.
@ -134,10 +148,5 @@ class {clsname}({parents}):
fields = '{' + (', '.join(['\n\t%s: %s' % (repr(emfield.uid),data_handler_constructor(emfield)) for emfield in em_class.fields()])) + '}', fields = '{' + (', '.join(['\n\t%s: %s' % (repr(emfield.uid),data_handler_constructor(emfield)) for emfield in em_class.fields()])) + '}',
) )
bootstrap += "\n" bootstrap += "\n"
for em_class in get_classes(model):
# Dyncode datasource bootstrap instructions
bootstrap += """{classname}._init_datasources()
""".format(
classname = LeObject.name2objname(em_class.uid))
return res, set(imports), bootstrap return res, set(imports), bootstrap

View file

@ -229,11 +229,10 @@ a read only as a read&write datasource"
ds_conf = getattr(ds_conf, ds_name) ds_conf = getattr(ds_conf, ds_name)
#Checks that the datasource plugin exists #Checks that the datasource plugin exists
ds_plugin_module = Plugin.get(ds_plugin).module ds_plugin_module = Plugin.get(ds_plugin).loader_module()
try: try:
datasource_class = getattr(ds_plugin_module, "Datasource") datasource_class = getattr(ds_plugin_module, "Datasource")
except AttributeError as e: except AttributeError as e:
raise e
expt_msg += "The datasource plugin %s seems to be invalid. Error \ expt_msg += "The datasource plugin %s seems to be invalid. Error \
raised when trying to import Datasource" raised when trying to import Datasource"
expt_msg %= ds_identifier expt_msg %= ds_identifier

View file

@ -61,7 +61,10 @@ class Plugin(object):
self.name = plugin_name self.name = plugin_name
self.path = self.plugin_path(plugin_name) self.path = self.plugin_path(plugin_name)
##@brief Stores the plugin module
self.module = None self.module = None
##@breif Stores the plugin loader module
self.__loader_module = None
self.__confspecs = dict() self.__confspecs = dict()
self.loaded = False self.loaded = False
@ -110,6 +113,7 @@ class Plugin(object):
##@brief Try to import a file from a variable in __init__.py ##@brief Try to import a file from a variable in __init__.py
#@param varname str : The variable name #@param varname str : The variable name
#@return loaded module
#@throw AttributeError if varname not found #@throw AttributeError if varname not found
#@throw ImportError if the file fails to be imported #@throw ImportError if the file fails to be imported
#@throw PluginError if the filename was not valid #@throw PluginError if the filename was not valid
@ -208,7 +212,7 @@ class Plugin(object):
#Loading the plugin #Loading the plugin
try: try:
self._import_from_init_var(LOADER_FILENAME_VARNAME) self.__loader_module = self._import_from_init_var(LOADER_FILENAME_VARNAME)
except AttributeError: except AttributeError:
msg = "Malformed plugin {plugin}. No {varname} found in __init__.py" msg = "Malformed plugin {plugin}. No {varname} found in __init__.py"
msg = msg.format( msg = msg.format(
@ -224,6 +228,11 @@ class Plugin(object):
logger.debug("Plugin '%s' loaded" % self.name) logger.debug("Plugin '%s' loaded" % self.name)
self.loaded = True self.loaded = True
def loader_module(self):
if not self.loaded:
raise RuntimeError("Plugin %s not loaded yet."%self.name)
return self.__loader_module
##@brief Call load method on every pre-loaded plugins ##@brief Call load method on every pre-loaded plugins
# #
# Called by loader to trigger hooks registration. # Called by loader to trigger hooks registration.
@ -245,6 +254,9 @@ class Plugin(object):
msg += "\n\t%20s : %s" % (name,e) msg += "\n\t%20s : %s" % (name,e)
msg += "\n" msg += "\n"
raise PluginError(msg) raise PluginError(msg)
from lodel.plugin.hooks import LodelHook
LodelHook.call_hook(
"lodel2_plugins_loaded", cls, cls._plugin_instances)
##@return a copy of __confspecs attr ##@return a copy of __confspecs attr
@property @property

View file

@ -1,5 +1,5 @@
from lodel.settings.validator import SettingValidator from lodel.settings.validator import SettingValidator
from .main import DummyDatasource as Datasource from .datasource import DummyDatasource as Datasource
__loader__ = 'main.py' __loader__ = 'main.py'
__plugin_deps__ = [] __plugin_deps__ = []

View file

@ -1,53 +1,9 @@
#-*- coding:utf-8 -*- #-*- coding:utf-8 -*-
class DummyDatasource(object): from lodel.plugin import LodelHook
from .datasource import DummyDatasource as Datasource
def __init__(self, *conn_args, **conn_kwargs): @LodelHook('datasources_migration_init')
self.conn_args = conn_args def dummy_migration_handler_init():
self.conn_kwargs = conn_kwargs from .migration_handler import DummyMigrationHandler as migration_handler
## @brief returns a selection of documents from the datasource
# @param target_cls Emclass
# @param field_list list
# @param filters list : List of filters
# @param rel_filters list : List of relational filters
# @param order list : List of column to order. ex: order = [('title', 'ASC'),]
# @param group list : List of tupple representing the column to group together. ex: group = [('title', 'ASC'),]
# @param limit int : Number of records to be returned
# @param offset int: used with limit to choose the start record
# @param instanciate bool : If true, the records are returned as instances, else they are returned as dict
# @return list
def select(self, target_cls, field_list, filters, rel_filters=None, order=None, group=None, limit=None, offset=0,
instanciate=True):
pass
##@brief Deletes records according to given filters
#@param target Emclass : class of the record to delete
#@param filters list : List of filters
#@param relational_filters list : List of relational filters
#@return int : number of deleted records
def delete(self, target, filters, relational_filters):
pass
## @brief updates records according to given filters
#@param target Emclass : class of the object to insert
#@param filters list : List of filters
#@param rel_filters list : List of relational filters
#@param upd_datas dict : datas to update (new values)
#@return int : Number of updated records
def update(self, target, filters, relational_filters, upd_datas):
pass
## @brief Inserts a record in a given collection
# @param target Emclass : class of the object to insert
# @param new_datas dict : datas to insert
# @return the inserted uid
def insert(self, target, new_datas):
pass
## @brief Inserts a list of records in a given collection
# @param target Emclass : class of the objects inserted
# @param datas_list list : list of dict
# @return list : list of the inserted records' ids
def insert_multi(self, target, datas_list):
pass

View file

@ -1,3 +1,4 @@
#-*- coding: utf-8 -*-
from .utils import connect, get_connection_args from .utils import connect, get_connection_args
__loader__ = "main.py" __loader__ = "main.py"
@ -12,13 +13,4 @@ __fullname__ = "MongoDB plugin"
# #
# @return bool|str : True if all the checks are OK, an error message if not # @return bool|str : True if all the checks are OK, an error message if not
def _activate(): def _activate():
default_connection_args = get_connection_args()
connection_check = connect(
default_connection_args['host'],
default_connection_args['port'],
default_connection_args['db_name'],
default_connection_args['username'],
default_connection_args['password'])
if not connection_check:
return False
return True return True

View file

@ -1,11 +1,8 @@
from lodel.plugin import LodelHook from lodel.plugin import LodelHook
from .datasource import MongoDbDatasource as Datasource
@LodelHook('mongodb_mh_init') @LodelHook('datasources_migration_init')
def mongodb_migration_handler_init(): def mongodb_migration_handler_init():
import plugins.mongodb_datasource.migration_handler as migration_handler import plugins.mongodb_datasource.migration_handler as migration_handler
@LodelHook('mongodb_ds_init')
def mongodb_datasource_init():
import plugins.mongodb_datasource.datasource as datasource