Commit 4059e29e authored by Vincent Pelletier's avatar Vincent Pelletier

ZSQLCatalog.SQLCatalog: Expand scriptable keys further.

Add support for "like" auto-detection and use as default comparison
operator.
Allows mimicking KeywordKey and DefaultKey with 2 parameters, in addition
to already-supported simple SearchKey.
parent f98f1411
...@@ -1832,7 +1832,16 @@ class Catalog(Folder, ...@@ -1832,7 +1832,16 @@ class Catalog(Folder,
else: else:
search_key = self.getSearchKey(key, 'RelatedKey') search_key = self.getSearchKey(key, 'RelatedKey')
else: else:
search_key = SearchKeyWrapperForScriptableKey(key, script) func_code = script.func_code
search_key = (
AdvancedSearchKeyWrapperForScriptableKey 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 SearchKeyWrapperForScriptableKey
)(key, script)
related_key_definition = None related_key_definition = None
return search_key, related_key_definition return search_key, related_key_definition
...@@ -2565,30 +2574,76 @@ class SearchKeyWrapperForScriptableKey(SearchKey.SearchKey.SearchKey): ...@@ -2565,30 +2574,76 @@ class SearchKeyWrapperForScriptableKey(SearchKey.SearchKey.SearchKey):
This SearchKey is a simple wrapper around a ScriptableKey, so such script This SearchKey is a simple wrapper around a ScriptableKey, so such script
can be used in place of a regular SearchKey. can be used in place of a regular SearchKey.
""" """
security = ClassSecurityInfo()
def __init__(self, column, script): def __init__(self, column, script):
self.script = 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) super(SearchKeyWrapperForScriptableKey, self).__init__(column)
def buildQuery(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, ),
)
if logical_operator is not None:
raise ValueError(
'ScriptableKey ignores logical operators (%r given).' % (logical_operator, ),
)
if comparison_operator:
raise ValueError(
'ScriptableKey ignores comparison operators (%r given).' % (comparison_operator, ),
)
return self.script(search_value)
class AdvancedSearchKeyWrapperForScriptableKey(SearchKey.DefaultKey.DefaultKey):
"""
Similar to SearchKeyWrapperForScriptableKey, but exposes more of the SearchKey API.
"""
security = ClassSecurityInfo()
def __init__(self, column, script):
self.script = script
super(AdvancedSearchKeyWrapperForScriptableKey, self).__init__(column)
security.declarePublic('processSearchValue') security.declarePublic('processSearchValue')
def processSearchValue(self, *args, **kw): def processSearchValue(
self,
default_comparison_operator='=',
detect_like=False,
*args,
**kw
):
""" """
Expose _processSearchValue to self.script. Expose _processSearchValue to self.script.
Only callable from full-API scripts, as others do not get access to our Only callable from full-API scripts, as others do not get access to our
instance. instance.
""" """
# Note about patching self: this method is not reentrant, so (un)patching
# is fine.
if not detect_like:
self._guessComparisonOperator = super(
# Note: not AdvancedSearchKeyWrapperForScriptableKey, trying to get
# above it.
SearchKey.DefaultKey.DefaultKey,
self,
)._guessComparisonOperator
# Note: No need to clean this up, it will be overwritten on next call.
self.default_comparison_operator = default_comparison_operator
try:
return self._processSearchValue(*args, **kw) return self._processSearchValue(*args, **kw)
finally:
if not detect_like:
del self._guessComparisonOperator
def __buildQueryWithFiveArgumentsAPI(self, search_value, group=None, def buildQuery(
logical_operator=None, comparison_operator=None): self,
search_value,
group=None,
logical_operator=None,
comparison_operator=None,
):
""" """
Becomes buildQuery if self.script supports extra parameters. Becomes buildQuery if self.script supports extra parameters.
""" """
...@@ -2600,26 +2655,7 @@ class SearchKeyWrapperForScriptableKey(SearchKey.SearchKey.SearchKey): ...@@ -2600,26 +2655,7 @@ class SearchKeyWrapperForScriptableKey(SearchKey.SearchKey.SearchKey):
logical_operator=logical_operator, logical_operator=logical_operator,
comparison_operator=comparison_operator, comparison_operator=comparison_operator,
) )
InitializeClass(AdvancedSearchKeyWrapperForScriptableKey)
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, ),
)
if logical_operator is not None:
raise ValueError(
'ScriptableKey ignores logical operators (%r given).' % (logical_operator, ),
)
if comparison_operator:
raise ValueError(
'ScriptableKey ignores comparison operators (%r given).' % (comparison_operator, ),
)
return self.script(search_value)
InitializeClass(SearchKeyWrapperForScriptableKey)
from Operator import operator_dict from Operator import operator_dict
def getComparisonOperatorInstance(operator): def getComparisonOperatorInstance(operator):
......
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