Browse Source

Remove conflictsMerge branch 'newlodel' of git.labocleo.org:lodel2 into newlodel

Conflicts:
	lodel/leapi/leobject.py
	lodel/leapi/query.py
prieto 8 years ago
parent
commit
96aa360702
5 changed files with 87 additions and 27 deletions
  1. 2
    2
      lodel/leapi/leobject.py
  2. 20
    18
      lodel/leapi/query.py
  3. 6
    3
      plugins/mongodb_datasource/utils.py
  4. 45
    4
      tests/leapi/test_leobject.py
  5. 14
    0
      tests/utils.py

+ 2
- 2
lodel/leapi/leobject.py View File

@@ -1,7 +1,6 @@
1 1
 #-*- coding: utf-8 -*-
2 2
 
3 3
 import importlib
4
-import warnings
5 4
 
6 5
 from lodel.plugin import Plugin
7 6
 from lodel import logger
@@ -145,7 +144,7 @@ class LeObject(object):
145 144
         mod = importlib.import_module(cls.__module__)
146 145
         try:
147 146
             return getattr(mod, leobject_name)
148
-        except AttributeError:
147
+        except (AttributeError, TypeError) :
149 148
             raise LeApiError("No LeObject named '%s'" % leobject_name)
150 149
     
151 150
     @classmethod
@@ -512,6 +511,7 @@ raised when trying to import Datasource"
512 511
         query_filter = list()
513 512
         for uid in uids:
514 513
             query_filter.append((uid, '=', self.data(uid)))
514
+
515 515
         query = LeDeleteQuery(self.name2class(self.__class__.__name__), query_filter)
516 516
 
517 517
         result = query.execute()

+ 20
- 18
lodel/leapi/query.py View File

@@ -33,10 +33,10 @@ class LeQuery(object):
33 33
     ##@brief Execute a query and return the result
34 34
     # @param **datas
35 35
     # @return the query result
36
-    # @see LeQuery.__query()
36
+    # @see LeQuery._query()
37 37
     #
38 38
     def execute(self, **datas):
39
-        if len(datas) > 0:
39
+        if 'datas' in datas and len(datas['datas']) > 0:
40 40
             self._target_class.check_datas_value(
41 41
                                                     datas['datas'],
42 42
                                                     **self._data_check_args)
@@ -46,7 +46,7 @@ class LeQuery(object):
46 46
         LodelHook.call_hook(    self._hook_prefix+'_pre',
47 47
                                 self._target_class,
48 48
                                 datas)
49
-        ret = self.__query(target = self._target_class, **datas)
49
+        ret = self._query(**datas)
50 50
         ret = LodelHook.call_hook(  self._hook_prefix+'_post',
51 51
                                     self._target_class,
52 52
                                     ret)
@@ -55,7 +55,7 @@ class LeQuery(object):
55 55
     ##@brief Childs classes implements this method to execute the query
56 56
     # @param **datas
57 57
     # @return query result
58
-    def __query(self, **datas):
58
+    def _query(self, **datas):
59 59
         raise NotImplementedError("Asbtract method")
60 60
     
61 61
     ##@return a dict with query infos
@@ -95,7 +95,7 @@ class LeFilteredQuery(LeQuery):
95 95
     def __init__(self, target_class, query_filters = None):
96 96
         super().__init__(target_class)
97 97
         ##@brief The query filter tuple(std_filter, relational_filters)
98
-        self.__query_filter = None
98
+        self._query_filter = None
99 99
         ##@brief Stores potential subqueries (used when a query implies
100 100
         # more than one datasource.
101 101
         #
@@ -108,23 +108,25 @@ class LeFilteredQuery(LeQuery):
108 108
     # This method takes care to execute subqueries before calling super execute
109 109
     def execute(self, datas = None):
110 110
         #copy originals filters
111
-        orig_filters = copy.copy(self.__query_filter)
112
-        std_filters, rel_filters = self.__query_filter
111
+        orig_filters = copy.copy(self._query_filter)
112
+        std_filters, rel_filters = self._query_filter
113 113
 
114 114
         for rfield, subq in self.subqueries:
115 115
             subq_res = subq.execute()
116 116
             std_filters.append(
117 117
                 (rfield, ' in ', subq_res))
118
-        self.__query_filter = (std_filters, rel_filters)
118
+        self._query_filter = (std_filters, rel_filters)
119 119
         try:
120
+
120 121
             filters, rel_filters = self.__query_filter
121 122
             res = super().execute(filters = filters, rel_filters = rel_filters, datas)
122 123
         except Exception as e:
123 124
             #restoring filters even if an exception is raised
124 125
             self.__query_filter = orig_filters
126
+
125 127
             raise e #reraise
126 128
         #restoring filters
127
-        self.__query_filter = orig_filters
129
+        self._query_filter = orig_filters
128 130
         return res
129 131
 
130 132
     ##@brief Add filter(s) to the query
@@ -185,8 +187,8 @@ class LeFilteredQuery(LeQuery):
185 187
                     ((rfield, ref_dict), op, value))
186 188
         #deduplication of std filters
187 189
         filters_orig = list(set(filters_orig))
188
-        # Sets __query_filter attribute of self query
189
-        self.__query_filter = (filters_orig, result_rel_filters)
190
+        # Sets _query_filter attribute of self query
191
+        self._query_filter = (filters_orig, result_rel_filters)
190 192
 
191 193
         #Sub queries creation
192 194
         subq = list()
@@ -204,7 +206,7 @@ class LeFilteredQuery(LeQuery):
204 206
     ##@return informations
205 207
     def dump_infos(self):
206 208
         ret = super().dump_infos()
207
-        ret['query_filter'] = self.__query_filter
209
+        ret['query_filter'] = self._query_filter
208 210
         ret['subqueries'] = self.subqueries
209 211
         return ret
210 212
 
@@ -212,7 +214,7 @@ class LeFilteredQuery(LeQuery):
212 214
         res = "<{classname} target={target_class} query_filter={query_filter}"
213 215
         res = ret.format(
214 216
             classname=self.__class__.__name__,
215
-            query_filter = self.__query_filter,
217
+            query_filter = self._query_filter,
216 218
             target_class = self._target_class)
217 219
         if len(self.subqueries) > 0:
218 220
             for n,subq in enumerate(self.subqueries):
@@ -459,7 +461,7 @@ class LeInsertQuery(LeQuery):
459 461
     
460 462
     ## @brief Implements an insert query operation, with only one insertion
461 463
     # @param new_datas : datas to be inserted
462
-    def __query(self, datas):
464
+    def _query(self, datas):
463 465
         datas = self._target_class.prepare_datas(datas, True, False)
464 466
         nb_inserted = self._rw_datasource.insert(self._target_class,datas)
465 467
         if nb_inserted < 0:
@@ -468,7 +470,7 @@ class LeInsertQuery(LeQuery):
468 470
     """
469 471
     ## @brief Implements an insert query operation, with multiple insertions
470 472
     # @param datas : list of **datas to be inserted
471
-    def __query(self, datas):
473
+    def _query(self, datas):
472 474
         nb_inserted = self._datasource.insert_multi(
473 475
             self._target_class,datas_list)
474 476
         if nb_inserted < 0:
@@ -525,7 +527,7 @@ target to LeUpdateQuery constructor"
525 527
     #@returns the number of updated items
526 528
     #@todo change stategy for instance update. Datas should be allowed 
527 529
     #for execute method (and query)
528
-    def __query(self, filters, rel_filters, datas):
530
+    def _query(self, filters, rel_filters, datas):
529 531
         uid_name = self._target_class._uid[0]
530 532
         if self.__leobject_instance is not None:
531 533
             #Instance update
@@ -575,7 +577,7 @@ class LeDeleteQuery(LeFilteredQuery):
575 577
     #@param filters list : see @ref LeFilteredQuery
576 578
     #@param rel_filters list : see @ref LeFilteredQuery
577 579
     #@returns the number of deleted items
578
-    def __query(self, filters, rel_filters):
580
+    def _query(self, filters, rel_filters):
579 581
         nb_deleted = self._rw_datasource.delete(
580 582
             self._target_class, filters, rel_filters)
581 583
         return nb_deleted
@@ -666,7 +668,7 @@ class LeGetQuery(LeFilteredQuery):
666 668
 
667 669
     ##@brief Implements select query operations
668 670
     # @returns a list containing the item(s)
669
-    def __query(self):
671
+    def _query(self):
670 672
         # select datas corresponding to query_filter
671 673
         l_datas=self._ro_datasource.select(  self._target_class,
672 674
                                     list(self.field_list),

+ 6
- 3
plugins/mongodb_datasource/utils.py View File

@@ -54,10 +54,13 @@ def connection_string(host, port, db_name, username, password):
54 54
     return 'mongodb://%s:%s@%s:%s' % (username, password, host, port)
55 55
 
56 56
 
57
+def connection(host, port, username, password):
58
+    return MongoClient(connection_string(host, port, '', username, password))
59
+
60
+
57 61
 def connect(host, port, db_name, username, password):
58
-    connection = MongoClient(
59
-        connection_string(host, port, db_name, username, password))
60
-    database = connection[db_name]
62
+    conn = connection(host, port, username, password)
63
+    database = conn[db_name]
61 64
     return database
62 65
 
63 66
 

+ 45
- 4
tests/leapi/test_leobject.py View File

@@ -59,11 +59,12 @@ class LeObjectDummyTestCase(unittest.TestCase):
59 59
     def test_bad_name2class(self):
60 60
         """ Testing failures of the class method that returns a dynamic object
61 61
             given it's name """
62
-        badnames = ['foobar', 'LeObject', 'str', str, None, 42]
62
+        badnames = ['foobar', 'str', str, None, 42]
63 63
         callers = [dyncode.Object, dyncode.Person, dyncode.Entitie]
64 64
         for caller in callers:
65 65
             for badname in badnames:
66
-                with self.assertRaises(LeApiError):
66
+                with self.assertRaises(LeApiError, msg="LeApiError not raised \
67
+but invalid name %s was given" % badname):
67 68
                     caller.name2class(badname)
68 69
 
69 70
     def test_abstract_name2class(self):
@@ -112,6 +113,8 @@ class LeObjectQueryMockTestCase(unittest.TestCase):
112 113
     """ Testing LeObject mocking LeQuery objects """
113 114
 
114 115
     def test_insert(self):
116
+        """ Checking that LeObject insert method calls LeInsertQuery
117
+            correctly """
115 118
         datas = {'lastname': 'foo', 'firstname': 'bar'}
116 119
         with patch.object(
117 120
             LeInsertQuery, '__init__', return_value = None) as mock_init:
@@ -125,5 +128,43 @@ class LeObjectQueryMockTestCase(unittest.TestCase):
125 128
             ret = dyncode.Person.insert(datas)
126 129
             self.AssertEqual(ret, 42, 'Bad return value forwarding')
127 130
             mock_insert.assert_called_once_with(datas)
128
-                
129
-        
131
+    
132
+    def test_delete(self):
133
+        """ Checking that LeObject delete method calls LeDeleteQuery
134
+            correctly """
135
+        with patch.object(
136
+            LeDeleteQuery, '__init__', return_value = None) as mock_init:
137
+
138
+            inst = dyncode.Person(
139
+                lodel_id = 1, firstname = "foo", lastname = "bar")
140
+            inst.delete()
141
+            mock_init.assert_called_once_with(
142
+                dyncode.Person, [('lodel_id', '=', 1)])
143
+
144
+        with patch.object(
145
+            LeDeleteQuery, 'execute', return_value = 1) as mock_execute:
146
+
147
+            inst = dyncode.Person(
148
+                lodel_id = 1, firstname = "foo", lastname = "bar")
149
+            ret = inst.delete()
150
+            self.assertEqual(ret, 1, 'Bad return value forwarding')
151
+            mock_execute.assert_called_once_with(
152
+                dyncode.Person, [('lodel_id', '=', 1)], [])
153
+
154
+    def test_delete_bundle(self):
155
+        """ Checking that LeObject delete_bundle method calls LeDeleteQuery
156
+            correctly """
157
+        with patch.object(
158
+            LeDeleteQuery, '__init__', return_value = None) as mock_init:
159
+            
160
+            dyncode.Person.delete_bundle(['lodel_id > 1'])
161
+            mock_init.assert_called_once_with(
162
+                dyncode.Person, ['lodel_id > 1'])
163
+
164
+        with patch.object(
165
+            LeDeleteQuery, 'execute', return_value = None) as mock_execute:
166
+            
167
+            dyncode.Person.delete_bundle(['lodel_id > 1'])
168
+            mock_init.assert_called_once_with(
169
+                dyncode.Person, [('lodel_id', '>', 1)], [])
170
+

+ 14
- 0
tests/utils.py View File

@@ -0,0 +1,14 @@
1
+from plugins.mongodb_datasource.utils import connection
2
+
3
+
4
+def datasource_tests_init(conn_args):
5
+    conn = connection(host=conn_args['host'],
6
+                      port=conn_args['port'],
7
+                      username=conn_args['username'],
8
+                      password=conn_args['password'])
9
+    database = conn[conn_args['db_name']]
10
+    return (conn, database)
11
+
12
+
13
+def datasource_tests_db_clean(conn, dbname):
14
+    conn.drop_database(dbname)

Loading…
Cancel
Save