Browse Source

Enhancement in datasources plugins handling

- now datasources are handled in LeObject child classes
- plugins module now have a method to retrieve a plugin module
Yann Weber 8 years ago
parent
commit
84717328e3

+ 50
- 0
lodel/leapi/leobject.py View File

@@ -2,6 +2,11 @@
2 2
 
3 3
 import importlib
4 4
 
5
+from lodel.plugin import Plugins
6
+from lodel import logger
7
+from lodel.settings import Settings
8
+from lodel.settings.utils import SettingsError
9
+
5 10
 class LeApiErrors(Exception):
6 11
     ##@brief Instanciate a new exceptions handling multiple exceptions
7 12
     # @param msg str : Exception message
@@ -179,6 +184,51 @@ class LeObject(object):
179 184
         except KeyError:
180 185
             raise NameError("No field named '%s' in %s" % ( fieldname,
181 186
                                                             cls.__name__))
187
+    
188
+    ##@brief Replace the _datasource attribute value by a datasource instance
189
+    #
190
+    # This method is used once at dyncode load to replace the datasource string
191
+    # by a datasource instance to avoid doing this operation for each query
192
+    @classmethod
193
+    def _init_datasource(cls):
194
+        expt_msg = "In LeAPI class '%s' " % cls.__name__
195
+        if cls._datasource not in Settings.datasources._fields:
196
+            expt_msg += "Unknow or unconfigured datasource %s"
197
+            expt_msg %= (cls._datasource, cls.__name__)
198
+            raise SettingsError(expt_msg)
199
+
200
+        ds_identifier = getattr(Settings.datasources, cls._datasource)
201
+        try:
202
+            ds_identifier = getattr(ds_identifier, 'identifier')
203
+        except NameError:
204
+            expt_msg += "Datasource %s is missconfigured, missing identifier."
205
+            expt_msg %= cls._datasource
206
+            raise SettingsError(expt_msg)
207
+
208
+        ds_plugin, ds_name = ds_identifier.split('.')
209
+        #Checks that the datasource is configured
210
+        if ds_plugin not in Settings.datasource._fields:
211
+            expt_msg += "Unknown or unconfigured datasource plugin %s"
212
+            expt_msg %= ds_plugin
213
+            raise SettingsError(expt_msg)
214
+
215
+        ds_conf = getattr(Settings.datasource, ds_plugin)
216
+        if ds_name not in ds_conf._fields:
217
+            expt_msg += "Unknown or unconfigured datasource instance %s"
218
+            expt_msg %= ds_identifier
219
+            raise SettingsError(expt_msg)
220
+
221
+        ds_conf = getattr(ds_conf, ds_name)
222
+        #Checks that the datasource plugin exists
223
+        ds_plugin_module = Plugins.plugin_module(ds_plugin)
224
+        try:
225
+            cls._datasource = getattr(ds_plugin_module, "Datasource")
226
+        except AttributeError as e:
227
+            raise e
228
+            expt_msg += "The datasource plugin %s seems to be invalid. Error raised when trying to import Datasource"
229
+            expt_msg %= ds_identifier
230
+            raise SettingsError(expt_msg)
231
+        logger.debug("Datasource initialized for LeObject %s" % cls.__name__)
182 232
 
183 233
     ##@brief Read only access to all datas
184 234
     # @note for fancy data accessor use @ref LeObject.g attribute @ref LeObjectValues instance

+ 16
- 5
lodel/plugin/plugins.py View File

@@ -2,7 +2,9 @@
2 2
 
3 3
 import os.path
4 4
 
5
+import importlib
5 6
 from importlib.machinery import SourceFileLoader, SourcelessFileLoader
7
+import plugins
6 8
 
7 9
 ## @package lodel.plugins Lodel2 plugins management
8 10
 #
@@ -15,7 +17,7 @@ from importlib.machinery import SourceFileLoader, SourcelessFileLoader
15 17
 ##@brief The package in wich we will load plugins modules
16 18
 VIRTUAL_PACKAGE_NAME = 'lodel.plugins_pkg'
17 19
 CONFSPEC_FILENAME = 'confspec.py'
18
-MAIN_FILENAME = 'main.py'
20
+MAIN_FILENAME = '__init__.py'
19 21
 CONFSPEC_VARNAME = 'CONFSPEC'
20 22
 
21 23
 class PluginError(Exception):
@@ -73,18 +75,27 @@ class Plugins(object):
73 75
     # @param plugin_name str : The plugin name
74 76
     @classmethod
75 77
     def load_plugin(cls, plugin_name):
78
+        cls.plugin_module(plugin_name)
79
+    
80
+    ##@brief Load a plugin module and return it
81
+    #@return the plugin module
82
+    @classmethod
83
+    def plugin_module(cls, plugin_name):
76 84
         cls.started()
77 85
         plugin_path = cls.plugin_path(plugin_name)
78 86
         plugin_module = '%s.%s' % ( VIRTUAL_PACKAGE_NAME,
79 87
                                     plugin_name)
80
-        main_module = plugin_module + '.main'
88
+        main_module = plugin_module
81 89
         main_source = plugin_path + MAIN_FILENAME
82 90
         try:
83 91
             loader = SourceFileLoader(main_module, main_source)
84
-            main_module = loader.load_module()
85
-        except ImportError:
92
+            module = loader.load_module()
93
+            return module
94
+        except ImportError as e:
95
+            raise e
86 96
             raise PluginError("Failed to load plugin '%s'. It seems that the plugin name is not valid" % plugin_name)
87
-        
97
+
98
+
88 99
     ##@brief Bootstrap the Plugins class
89 100
     @classmethod
90 101
     def bootstrap(cls):

+ 1
- 0
plugins/dummy_datasource/__init__.py View File

@@ -0,0 +1 @@
1
+from .main import DummyDatasource as Datasource

+ 1
- 1
plugins/dummy_datasource/confspec.py View File

@@ -3,7 +3,7 @@
3 3
 from lodel.settings.validator import SettingValidator
4 4
 
5 5
 CONFSPEC = {
6
-    'lodel2.datasource.dummy.*' : {
6
+    'lodel2.datasource.dummy_datasource.*' : {
7 7
         'dummy': (  None,
8 8
                     SettingValidator('dummy'))}
9 9
 }

+ 51
- 0
plugins/dummy_datasource/main.py View File

@@ -0,0 +1,51 @@
1
+#-*- coding:utf-8 -*-
2
+
3
+class DummyDatasource(object):
4
+    
5
+    def __init__(self, *conn_args, **conn_kwargs):
6
+        self.conn_args = conn_args
7
+        self.conn_kwargs = conn_kwargs
8
+
9
+    ## @brief returns a selection of documents from the datasource
10
+    # @param target_cls Emclass
11
+    # @param field_list list
12
+    # @param filters list : List of filters
13
+    # @param rel_filters list : List of relational filters
14
+    # @param order list : List of column to order. ex: order = [('title', 'ASC'),]
15
+    # @param group list : List of tupple representing the column to group together. ex: group = [('title', 'ASC'),]
16
+    # @param limit int : Number of records to be returned
17
+    # @param offset int: used with limit to choose the start record
18
+    # @param instanciate bool : If true, the records are returned as instances, else they are returned as dict
19
+    # @return list
20
+    def select(self, target_cls, field_list, filters, rel_filters=None, order=None, group=None, limit=None, offset=0,
21
+               instanciate=True):
22
+        pass
23
+
24
+    ## @brief Deletes one record defined by its uid
25
+    # @param target_cls Emclass : class of the record to delete
26
+    # @param uid dict|list : a dictionary of fields and values composing the unique identifier of the record or a list of several dictionaries
27
+    # @return int : number of deleted records
28
+    def delete(self, target_cls, uid):
29
+        pass
30
+
31
+    ## @brief updates one or a list of records
32
+    # @param target_cls Emclass : class of the object to insert
33
+    # @param uids list : list of uids to update
34
+    # @param datas dict : datas to update (new values)
35
+    # @return int : Number of updated records
36
+    def update(self, target_cls, uids, **datas):
37
+        pass
38
+
39
+    ## @brief Inserts a record in a given collection
40
+    # @param target_cls Emclass : class of the object to insert
41
+    # @param datas dict : datas to insert
42
+    # @return bool
43
+    def insert(self, target_cls, **datas):
44
+        pass
45
+
46
+    ## @brief Inserts a list of records in a given collection
47
+    # @param target_cls Emclass : class of the objects inserted
48
+    # @param datas_list
49
+    # @return list : list of the inserted records' ids
50
+    def insert_multi(self, target_cls, datas_list):
51
+        pass

Loading…
Cancel
Save