If the filter starting a conditional block is preceded by '!', the condition is negative. For example: !Fedora.14, RHEL.6.0: only qcow2 means "for everything except Fedora.14 and RHEL.6.0, allow only qcow2". Signed-off-by: Michael Goldish <mgoldish@xxxxxxxxxx> --- client/tests/kvm/kvm_config.py | 59 +++++++++++++++++++++++++++------------- 1 files changed, 40 insertions(+), 19 deletions(-) diff --git a/client/tests/kvm/kvm_config.py b/client/tests/kvm/kvm_config.py index b6e089b..4dbb1d4 100755 --- a/client/tests/kvm/kvm_config.py +++ b/client/tests/kvm/kvm_config.py @@ -137,6 +137,14 @@ class NoOnlyFilter(Filter): class OnlyFilter(NoOnlyFilter): + def is_irrelevant(self, ctx, ctx_set, descendant_labels): + return self.match(ctx, ctx_set) + + + def requires_action(self, ctx, ctx_set, descendant_labels): + return not self.might_match(ctx, ctx_set, descendant_labels) + + def might_pass(self, failed_ctx, failed_ctx_set, ctx, ctx_set, descendant_labels): for word in self.filter: @@ -148,6 +156,14 @@ class OnlyFilter(NoOnlyFilter): class NoFilter(NoOnlyFilter): + def is_irrelevant(self, ctx, ctx_set, descendant_labels): + return not self.might_match(ctx, ctx_set, descendant_labels) + + + def requires_action(self, ctx, ctx_set, descendant_labels): + return self.match(ctx, ctx_set) + + def might_pass(self, failed_ctx, failed_ctx_set, ctx, ctx_set, descendant_labels): for word in self.filter: @@ -165,6 +181,13 @@ class Condition(NoFilter): self.content = [] +class NegativeCondition(OnlyFilter): + def __init__(self, line): + Filter.__init__(self, line.lstrip("!").rstrip(":")) + self.line = line + self.content = [] + + class Parser(object): """ Parse an input file or string that follows the KVM Test Config File format @@ -229,24 +252,15 @@ class Parser(object): if type(obj) is Op: new_content.append(t) continue - elif type(obj) is OnlyFilter: - if not obj.might_match(ctx, ctx_set, labels): - self._debug(" filter did not pass: %r (%s:%s)", - obj.line, filename, linenum) - failed_filters.append(t) - return False - elif obj.match(ctx, ctx_set): - continue - elif type(obj) is NoFilter: - if obj.match(ctx, ctx_set): + # obj is an OnlyFilter/NoFilter/Condition/NegativeCondition + if obj.requires_action(ctx, ctx_set, labels): + # This filter requires action now + if type(obj) is OnlyFilter or type(obj) is NoFilter: self._debug(" filter did not pass: %r (%s:%s)", obj.line, filename, linenum) failed_filters.append(t) return False - elif not obj.might_match(ctx, ctx_set, labels): - continue - elif type(obj) is Condition: - if obj.match(ctx, ctx_set): + else: self._debug(" conditional block matches: %r (%s:%s)", obj.line, filename, linenum) # Check and unpack the content inside this Condition @@ -259,9 +273,12 @@ class Parser(object): failed_filters.append(t) return False continue - elif not obj.might_match(ctx, ctx_set, labels): - continue - new_content.append(t) + elif obj.is_irrelevant(ctx, ctx_set, labels): + # This filter is no longer relevant and can be removed + continue + else: + # Keep the filter and check it again later + new_content.append(t) return True def might_pass(failed_ctx, @@ -429,7 +446,8 @@ class Parser(object): # Parse 'variants' if line == "variants:": # 'variants' is not allowed inside a conditional block - if isinstance(node, Condition): + if (isinstance(node, Condition) or + isinstance(node, NegativeCondition)): raise ParserError("'variants' is not allowed inside a " "conditional block", None, cr.filename, linenum) @@ -481,7 +499,10 @@ class Parser(object): cr.set_next_line(line[index:], indent, linenum) line = line[:index] try: - cond = Condition(line) + if line.startswith("!"): + cond = NegativeCondition(line) + else: + cond = Condition(line) except ParserError, e: e.line = line e.filename = cr.filename -- 1.7.3.4 -- To unsubscribe from this list: send the line "unsubscribe kvm" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html