Commit 3d8f2a5a authored by Vincent Pelletier's avatar Vincent Pelletier

ZSQLCatalog.SQLCatalog: Allow scriptable keys access to SearchKey API.

To avoid duplicating _processSearchValue.
parent 45a87733
......@@ -40,6 +40,7 @@ from ZODB.POSException import ConflictError
from Products.CMFCore import permissions
from Products.PythonScripts.Utility import allow_class
from compiler.consts import CO_VARKEYWORDS
from functools import wraps
import time
import urllib
......@@ -2564,14 +2565,47 @@ class SearchKeyWrapperForScriptableKey(SearchKey.SearchKey.SearchKey):
This SearchKey is a simple wrapper around a ScriptableKey, so such script
can be used in place of a regular SearchKey.
"""
security = ClassSecurityInfo()
def __init__(self, column, script):
self.script = script
func_code = script.func_code
self.buildQuery = self.__buildQueryWithFiveArgumentsAPI if (
# 5: search_value (under any name), "search_key", "group",
# "logical_operator", "comparison_operator". The last 4 are possible in
# any order.
func_code.co_argcount == 5 or
getattr(func_code, 'co_flags', 0) & CO_VARKEYWORDS
) else self.__buildQueryWithOldAPI
super(SearchKeyWrapperForScriptableKey, self).__init__(column)
def buildQuery(self, search_value, group=None, logical_operator=None,
comparison_operator=None):
# XXX: It would be better to extend ScriptableKey API to support other
# parameters.
security.declarePublic('processSearchValue')
def processSearchValue(self, *args, **kw):
"""
Expose _processSearchValue to self.script.
Only callable from full-API scripts, as others do not get access to our
instance.
"""
return self._processSearchValue(*args, **kw)
def __buildQueryWithFiveArgumentsAPI(self, search_value, group=None,
logical_operator=None, comparison_operator=None):
"""
Becomes buildQuery if self.script supports extra parameters.
"""
assert logical_operator in (None, 'and', 'or'), repr(logical_operator)
return self.script(
search_value,
search_key=self,
group=group,
logical_operator=logical_operator,
comparison_operator=comparison_operator,
)
def __buildQueryWithOldAPI(self, search_value, group=None,
logical_operator=None, comparison_operator=None):
"""
Becomes buildQuery if self.script does not support extra parameters.
"""
if group is not None:
raise ValueError(
'ScriptableKey cannot be used inside a group (%r given).' % (group, ),
......@@ -2585,6 +2619,7 @@ class SearchKeyWrapperForScriptableKey(SearchKey.SearchKey.SearchKey):
'ScriptableKey ignores comparison operators (%r given).' % (comparison_operator, ),
)
return self.script(search_value)
InitializeClass(SearchKeyWrapperForScriptableKey)
from Operator import operator_dict
def getComparisonOperatorInstance(operator):
......
......@@ -170,7 +170,10 @@ class DummyCatalog(SQLCatalog):
sql_catalog_keyword_search_keys = ('keyword', )
sql_catalog_datetime_search_keys = ('date', )
sql_catalog_full_text_search_keys = ('old_fulltext', )
sql_catalog_scriptable_keys = ('scriptable_keyword | scriptableKeyScript', )
sql_catalog_scriptable_keys = (
'scriptable_keyword | scriptableKeyScript',
'scriptable_keyword_5args | scriptableKeyScriptFiveArguments',
)
sql_catalog_search_keys = ('fulltext | MroongaFullTextKey',
'fulltext_boolean | MroongaBooleanFullTextKey',)
......@@ -218,6 +221,39 @@ class DummyCatalog(SQLCatalog):
"""
return SimpleQuery(comparison_operator='=', keyword=value)
@staticmethod
def scriptableKeyScriptFiveArguments(
value,
search_key,
group,
logical_operator,
comparison_operator,
):
"""
Mimics a scriptable key (PythonScript) subobject, using the SearchKey API.
"""
operator_value_dict, logical_operator, _ = search_key.processSearchValue(
search_value=value,
default_logical_operator=logical_operator,
comparison_operator=comparison_operator,
)
query_list = [
SimpleQuery(
keyword=value_list[0], # XXX: Fine for tests, bad in general.
comparison_operator=comparison_operator,
group=group,
)
for comparison_operator, value_list in operator_value_dict.iteritems()
]
if len(query_list) == 1:
return query_list[0]
if query_list:
return ComplexQuery(
query_list,
logical_operator=logical_operator,
)
return SimpleQuery(uid=-1)
class TestSQLCatalog(ERP5TypeTestCase):
def setUp(self):
self._catalog = DummyCatalog('dummy_catalog')
......@@ -535,6 +571,8 @@ class TestSQLCatalog(ERP5TypeTestCase):
{'scriptable_keyword': '%a%'})
self.catalog(ReferenceQuery(ReferenceQuery(operator='=', keyword='%a%'), operator='and'),
{'default': 'scriptable_keyword:%a%'})
self.catalog(ReferenceQuery(ReferenceQuery(operator='!=', keyword='a'), operator='and'),
{'scriptable_keyword_5args': '!=a'})
def test_008_testRawKey(self):
self.catalog(ReferenceQuery(ReferenceQuery(operator='=', default='%a%'), operator='and'),
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment