1
0
Fork 0
mirror of https://github.com/yweber/lodel2.git synced 2025-10-21 16:49:02 +02:00

Add tests for filtered queries + bugfixes

- adds tests on filter parse & check
 - standart filters parse & check
 - relational filters parse & check
- bugfixes related to tests in query.py
- update the example and the test EM
- bugfixes in admin script
This commit is contained in:
Yann 2016-05-25 12:23:41 +02:00
commit 9781577cb6
7 changed files with 72 additions and 10 deletions

Binary file not shown.

View file

@ -5,7 +5,7 @@ plugins_path = plugins
plugins = dummy, webui
[lodel2.logging.stderr]
level = DEBUG
level = ERROR
filename = -
context = True

View file

@ -77,7 +77,10 @@ class Hierarch(MultipleRef):
# @param max_depth int | None : limit of depth
# @param max_childs int | Nine : maximum number of childs by nodes
def __init__(self, back_reference, max_depth = None, max_childs = None, **kwargs):
super().__init__(back_reference = back_reference, max_depth = max_depth, )
super().__init__( back_reference = back_reference,
max_depth = max_depth,
max_childs = max_childs,
**kwargs)
def _check_data_value(self, value):
value, expt = super()._check_data_value(value)

View file

@ -183,6 +183,7 @@ class LeFilteredQuery(LeQuery):
err_l["filter %d" % i] = e
for field, operator, value in filters:
err_key = "%s %s %s" % (field, operator, value) #to push in err_l
# Spliting field name to be able to detect a relational field
field_spl = field.split('.')
if len(field_spl) == 2:
@ -198,19 +199,33 @@ field name" % fieldname)
if isinstance(ret, Exception):
err_l[field] = ret
continue
# Check that the field is relational if ref_field given
if ref_field is not None and not cls.field(field).is_reference():
field_datahandler = self._target_class.field(field)
if ref_field is not None and not field_datahandler.is_reference():
# inconsistency
err_l[field] = NameError( "The field '%s' in %s is not\
err_l[field] = NameError( "The field '%s' in %s is not \
a relational field, but %s.%s was present in the filter"
% ( field,
self._target_class.__name__,
field,
ref_field))
# Prepare relational field
if self._target_class.field(field).is_reference():
if field_datahandler.is_reference():
#Relationnal field
if ref_field is None:
# ref_field default value
ref_uid = set([ lc._uid for lc in field_datahandler.linked_classes])
if len(ref_uid) == 1:
ref_field = ref_uid[0]
else:
if len(ref_uid) > 1:
err_l[err_key] = RuntimeError("The referenced classes are identified by fields with different name. Unable to determine wich field to use for the reference")
else:
err_l[err_key] = RuntimeError("Unknow error when trying to determine wich field to use for the relational filter")
continue
# Prepare relational field
ret = self._prepare_relational_fields(field, ref_field)
if isinstance(ret, Exception):
err_l[field] = ret
err_l[err_key] = ret
continue
else:
rel_filters.append((ret, operator, value))
else:
@ -221,6 +236,30 @@ a relational field, but %s.%s was present in the filter"
"Error while preparing filters : ",
err_l)
return (res_filters, rel_filters)
## @brief Prepare & check relational field
#
# The result is a tuple with (field, ref_field, concerned_classes), with :
# - field the target_class field name
# - ref_field the concerned_classes field names
# - concerned_classes a set of concerned LeObject classes
# @param field str : The target_class field name
# @param ref_field str : The referenced class field name
# @return a tuple(field, concerned_classes, ref_field) or an Exception class instance
def _prepare_relational_fields(self,field, ref_field):
field_dh = self._target_class.field(field)
concerned_classes = []
linked_classes = [] if field_dh.linked_classes is None else field_dh.linked_classes
for l_class in linked_classes:
try:
l_class.field(ref_field)
concerned_classes.append(l_class)
except KeyError:
pass
if len(concerned_classes) > 0:
return (field, ref_field, concerned_classes)
else:
return ValueError("None of the linked class of field %s has a field named '%s'" % (field, ref_field))
## @brief Check and split a query filter
# @note The query_filter format is "FIELD OPERATOR VALUE"
@ -249,7 +288,7 @@ a relational field, but %s.%s was present in the filter"
for operator in cls._query_operators[1:]:
op_re_piece += '|(%s)'%operator.replace(' ', '\s')
op_re_piece += ')'
cls._query_re = re.compile('^\s*(?P<field>(((superior)|(subordinate))\.)?[a-z_][a-z0-9\-_]*)\s*'+op_re_piece+'\s*(?P<value>.*)\s*$', flags=re.IGNORECASE)
cls._query_re = re.compile('^\s*(?P<field>([a-z_][a-z0-9\-_]*\.)?[a-z_][a-z0-9\-_]*)\s*'+op_re_piece+'\s*(?P<value>.*)\s*$', flags=re.IGNORECASE)
pass
@classmethod

View file

@ -4,7 +4,9 @@ import sys
import os, os.path
sys.path.append(os.path.dirname(os.getcwd()+'/..'))
import loader
from lodel.settings.settings import Settings as settings
settings('globconf.d')
from lodel.settings import Settings
def generate_dyncode(model_file, translator):
from lodel.editorial_model.model import EditorialModel

Binary file not shown.

View file

@ -115,3 +115,21 @@ class LeFilteredQueryTestCase(unittest.TestCase):
'lodel_id %s %s' % (op,v))
self.assertEqual( get_q.dump_infos()['query_filter'],
([('lodel_id',op,v)],[]))
def test_rel_filters(self):
""" Testing relational filters recognition """
test_datas = [ ( dyncode.Subsection,
'parent.lodel_id = 42',
( [],
[(('parent', 'lodel_id', [dyncode.Section]),'=','42')])),
( dyncode.Section,
'childs.lodel_id = 42',
( [],
[(('childs', 'lodel_id', [dyncode.Subsection]),'=','42')]))
]
for le_class, q_filter_arg, e_qfilter in test_datas:
get_q = LeGetQuery(le_class, q_filter_arg)
qinfos = get_q.dump_infos()
self.assertEqual( qinfos['query_filter'],
e_qfilter)