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:
parent
785a208d07
commit
9a82936fbf
7 changed files with 40 additions and 75 deletions
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -60,8 +60,11 @@ class Plugin(object):
|
||||||
self.started()
|
self.started()
|
||||||
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(
|
||||||
|
|
@ -223,7 +227,12 @@ class Plugin(object):
|
||||||
raise PluginError(msg)
|
raise PluginError(msg)
|
||||||
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
|
||||||
|
|
|
||||||
|
|
@ -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__ = []
|
||||||
|
|
|
||||||
|
|
@ -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):
|
|
||||||
self.conn_args = conn_args
|
|
||||||
self.conn_kwargs = conn_kwargs
|
|
||||||
|
|
||||||
## @brief returns a selection of documents from the datasource
|
@LodelHook('datasources_migration_init')
|
||||||
# @param target_cls Emclass
|
def dummy_migration_handler_init():
|
||||||
# @param field_list list
|
from .migration_handler import DummyMigrationHandler as migration_handler
|
||||||
# @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
|
|
||||||
|
|
|
||||||
|
|
@ -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()
|
return True
|
||||||
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
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue