mirror of
https://github.com/yweber/lodel2.git
synced 2025-10-26 09:39:01 +01:00
Written some tests for filtered queries + query re modifications
- the re for filter spliting is modified to better handle operators - added leading & trailing space to some operators
This commit is contained in:
parent
76f002d06c
commit
f402902b5b
5 changed files with 146 additions and 5 deletions
Binary file not shown.
|
|
@ -98,10 +98,10 @@ class LeFilteredQuery(LeQuery):
|
|||
'!=',
|
||||
'<',
|
||||
'>',
|
||||
'in',
|
||||
'not in',
|
||||
'like',
|
||||
'not like']
|
||||
' in ',
|
||||
' not in ',
|
||||
' like ',
|
||||
' not like ']
|
||||
|
||||
##@brief Regular expression to process filters
|
||||
_query_re = None
|
||||
|
|
@ -235,6 +235,7 @@ a relational field, but %s.%s was present in the filter"
|
|||
if not matches:
|
||||
raise ValueError("The query_filter '%s' seems to be invalid"%query_filter)
|
||||
result = (matches.group('field'), re.sub(r'\s', ' ', matches.group('operator'), count=0), matches.group('value').strip())
|
||||
result = [r.strip() for r in result]
|
||||
for r in result:
|
||||
if len(r) == 0:
|
||||
raise ValueError("The query_filter '%s' seems to be invalid"%query_filter)
|
||||
|
|
@ -248,7 +249,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>(((superior)|(subordinate))\.)?[a-z_][a-z0-9\-_]*)\s*'+op_re_piece+'\s*(?P<value>.*)\s*$', flags=re.IGNORECASE)
|
||||
pass
|
||||
|
||||
@classmethod
|
||||
|
|
|
|||
0
tests/leapi/query/__init__.py
Normal file
0
tests/leapi/query/__init__.py
Normal file
114
tests/leapi/query/test_filtere.py
Normal file
114
tests/leapi/query/test_filtere.py
Normal file
|
|
@ -0,0 +1,114 @@
|
|||
import unittest
|
||||
|
||||
import tests.loader_utils
|
||||
from tests.leapi.query.utils import dyncode_module as dyncode
|
||||
|
||||
from lodel.leapi.leobject import LeApiDataCheckError
|
||||
from lodel.leapi.query import LeDeleteQuery, LeUpdateQuery, LeGetQuery
|
||||
|
||||
class LeGetQueryTestCase(unittest.TestCase):
|
||||
|
||||
def test_init_default(self):
|
||||
""" Testing GetQuery instanciation default values"""
|
||||
tclass_list = [ dyncode.Object,
|
||||
dyncode.Entry,
|
||||
dyncode.Person,
|
||||
dyncode.Text,
|
||||
dyncode.Section,
|
||||
dyncode.Publication,
|
||||
dyncode.Text_Person,
|
||||
]
|
||||
for tclass in tclass_list:
|
||||
get_q = LeGetQuery(tclass, [])
|
||||
qinfos = get_q.dump_infos()
|
||||
self.assertEqual( set(qinfos['field_list']),
|
||||
set(tclass.fieldnames(True)))
|
||||
self.assertEqual( qinfos['limit'],
|
||||
None)
|
||||
self.assertEqual( qinfos['offset'],
|
||||
0)
|
||||
self.assertEqual( qinfos['group'],
|
||||
None)
|
||||
self.assertEqual( qinfos['order'],
|
||||
None)
|
||||
self.assertEqual( qinfos['query_filter'],
|
||||
([],[]))
|
||||
self.assertEqual( qinfos['target_class'],
|
||||
tclass)
|
||||
|
||||
class LeFilteredQueryTestCase(unittest.TestCase):
|
||||
|
||||
q_classes = [ LeDeleteQuery, LeUpdateQuery, LeGetQuery ]
|
||||
|
||||
def test_filters(self):
|
||||
""" Testing FilteredQuery filters handling """
|
||||
test_datas = [ ( 'lodel_id = 42',
|
||||
( [('lodel_id','=','42')],
|
||||
[])),
|
||||
( 'lodel_id <= 42',
|
||||
( [('lodel_id','<=','42')],
|
||||
[])),
|
||||
( ['lodel_id <= 42'],
|
||||
( [('lodel_id','<=','42')],
|
||||
[])),
|
||||
( ('lodel_id <= 42',),
|
||||
( [('lodel_id','<=','42')],
|
||||
[])),
|
||||
( ['lodel_id <= 42','lodel_id >= 33'],
|
||||
( [ ('lodel_id','<=','42'),
|
||||
('lodel_id', '>=','33')],
|
||||
[])),
|
||||
]
|
||||
for q_class in self.q_classes:
|
||||
for q_filter_arg, e_qfilter in test_datas:
|
||||
get_q = q_class(dyncode.Publication, q_filter_arg)
|
||||
self.assertEqual( get_q.dump_infos()['query_filter'],
|
||||
e_qfilter)
|
||||
|
||||
def test_invalid_filters(self):
|
||||
""" Testing invalid filters detection """
|
||||
invalid_filters = ( 'lodel_id',
|
||||
'',
|
||||
'"',
|
||||
"'",
|
||||
"not_exists != bar",
|
||||
"lodel_id # bar",
|
||||
"lodel_id ind 42,43",
|
||||
"lodel_id llike 42",
|
||||
('lodel_id', '', '42'),
|
||||
)
|
||||
for invalid_filter in invalid_filters:
|
||||
for q_class in self.q_classes:
|
||||
with self.assertRaises( LeApiDataCheckError,
|
||||
msg="for filter '%s'" % (invalid_filter,)):
|
||||
q_class(dyncode.Publication, invalid_filter)
|
||||
|
||||
|
||||
def test_filters_operators(self):
|
||||
""" Testing FilteredQuery filters operator recognition """
|
||||
ops = [ '=',
|
||||
'<=',
|
||||
'>=',
|
||||
'!=',
|
||||
'<',
|
||||
'>',
|
||||
'in',
|
||||
'not in',
|
||||
'like',
|
||||
'not like']
|
||||
values = ( '42',
|
||||
'not in',
|
||||
'in',
|
||||
'like',
|
||||
'=',
|
||||
'!=',
|
||||
"'",
|
||||
'"',
|
||||
'"hello world !"')
|
||||
for q_class in self.q_classes:
|
||||
for op in ops:
|
||||
for v in values:
|
||||
get_q = q_class( dyncode.Publication,
|
||||
'lodel_id %s %s' % (op,v))
|
||||
self.assertEqual( get_q.dump_infos()['query_filter'],
|
||||
([('lodel_id',op,v)],[]))
|
||||
26
tests/leapi/query/utils.py
Normal file
26
tests/leapi/query/utils.py
Normal file
|
|
@ -0,0 +1,26 @@
|
|||
#
|
||||
# Importing this file trigger dynamic code generation & load
|
||||
#
|
||||
# To use dynamic code import utils.dyncode_module as dyncode
|
||||
|
||||
import tempfile
|
||||
import os
|
||||
from importlib.machinery import SourceFileLoader
|
||||
|
||||
from lodel.leapi.lefactory import dyncode_from_em
|
||||
from lodel.editorial_model.translator import picklefile
|
||||
|
||||
def init_dyncode():
|
||||
f_handler, dyncode_file = tempfile.mkstemp( prefix="lodel2_tests",
|
||||
suffix="_dyncode")
|
||||
os.close(f_handler)
|
||||
model = picklefile.load('tests/editorial_model.pickle')
|
||||
source_code = dyncode_from_em(model)
|
||||
with os.fdopen(os.open(dyncode_file, os.O_WRONLY), 'w') as dynfd:
|
||||
dynfd.write(source_code)
|
||||
dyncode_module = SourceFileLoader("lodel.dyncode", dyncode_file).load_module()
|
||||
os.unlink(dyncode_file)
|
||||
return dyncode_module
|
||||
|
||||
dyncode_module = init_dyncode()
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue