Fix tag expression bugs, move work to searchhelpers

Fix handling of bad tags, bad syntax, empty expression. Remove unnecessary warning_bag from matcher builder
This commit is contained in:
voussoir 2017-03-31 21:52:49 -07:00
parent 884b1a1aa5
commit 241d1466eb
2 changed files with 56 additions and 21 deletions

View file

@ -768,24 +768,17 @@ class PDBPhotoMixin:
self._cached_frozen_children = frozen_children self._cached_frozen_children = frozen_children
if tag_expression: if tag_expression:
expression_tree = expressionmatch.ExpressionTree.parse(tag_expression) tag_expression_tree = searchhelpers.tag_expression_tree_builder(
expression_tree.map(self.normalize_tagname) tag_expression=tag_expression,
expression_matcher = searchhelpers.tag_expression_matcher_builder( photodb=self,
frozen_children, frozen_children=frozen_children,
warning_bag=warning_bag, warning_bag=warning_bag,
) )
for node in expression_tree.walk_leaves(): if tag_expression_tree is None:
if node.token in frozen_children: tag_expression = None
continue
exc = exceptions.NoSuchTag(node.token)
if warning_bag is not None:
warning_bag.add(exc.error_message)
node.token = None
else: else:
raise exc print(tag_expression_tree)
tag_match_function = searchhelpers.tag_expression_matcher_builder(frozen_children)
expression_tree.prune()
if filename: if filename:
filename_tree = expressionmatch.ExpressionTree.parse(filename) filename_tree = expressionmatch.ExpressionTree.parse(filename)
@ -859,9 +852,9 @@ class PDBPhotoMixin:
continue continue
if tag_expression: if tag_expression:
success = expression_tree.evaluate( success = tag_expression_tree.evaluate(
photo_tags, photo_tags,
match_function=expression_matcher, match_function=tag_match_function,
) )
if not success: if not success:
#print('Failed tag expression') #print('Failed tag expression')

View file

@ -3,6 +3,8 @@ from . import exceptions
from . import helpers from . import helpers
from . import objects from . import objects
from voussoirkit import expressionmatch
def build_query(orderby, notnulls): def build_query(orderby, notnulls):
query = 'SELECT * FROM photos' query = 'SELECT * FROM photos'
@ -330,8 +332,48 @@ def normalize_tag_mmf(tags, photodb, warning_bag=None):
return tagset return tagset
def tag_expression_matcher_builder(frozen_children, warning_bag=None): def tag_expression_tree_builder(
def matcher(photo_tags, tagname): tag_expression,
photodb,
frozen_children,
warning_bag=None
):
try:
expression_tree = expressionmatch.ExpressionTree.parse(tag_expression)
except expressionmatch.NoTokens:
return None
except Exception as exc:
warning_bag.add('Bad expression "%s"' % tag_expression)
return None
for node in expression_tree.walk_leaves():
try:
node.token = photodb.normalize_tagname(node.token)
except (exceptions.TagTooShort, exceptions.TagTooLong) as exc:
if warning_bag is not None:
warning_bag.add(exc.error_message)
node.token = None
else:
raise
if node.token is None:
continue
if node.token not in frozen_children:
exc = exceptions.NoSuchTag(node.token)
if warning_bag is not None:
warning_bag.add(exc.error_message)
node.token = None
else:
raise exc
expression_tree.prune()
if expression_tree.token is None:
return None
return expression_tree
def tag_expression_matcher_builder(frozen_children):
def match_function(photo_tags, tagname):
''' '''
Used as the `match_function` for the ExpressionTree evaluation. Used as the `match_function` for the ExpressionTree evaluation.
@ -346,4 +388,4 @@ def tag_expression_matcher_builder(frozen_children, warning_bag=None):
options = frozen_children[tagname] options = frozen_children[tagname]
return any(option in photo_tags for option in options) return any(option in photo_tags for option in options)
return matcher return match_function