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:
parent
38a2448934
commit
9781577cb6
7 changed files with 72 additions and 10 deletions
Binary file not shown.
|
@ -5,7 +5,7 @@ plugins_path = plugins
|
|||
plugins = dummy, webui
|
||||
|
||||
[lodel2.logging.stderr]
|
||||
level = DEBUG
|
||||
level = ERROR
|
||||
filename = -
|
||||
context = True
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
@ -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)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue