1 # Copyright 2013 The Chromium Authors. All rights reserved. 2 # Use of this source code is governed by a BSD-style license that can be 3 # found in the LICENSE file. 4 5 import optparse 6 import re 7 8 from telemetry.internal.util import command_line 9 10 11 class _StoryMatcher(object): 12 def __init__(self, pattern): 13 self._regex = None 14 self.has_compile_error = False 15 if pattern: 16 try: 17 self._regex = re.compile(pattern) 18 except re.error: 19 self.has_compile_error = True 20 21 def __nonzero__(self): 22 return self._regex is not None 23 24 def HasMatch(self, story): 25 return self and bool( 26 self._regex.search(story.display_name) or 27 (story.name and self._regex.search(story.name))) 28 29 30 class _StoryTagMatcher(object): 31 def __init__(self, tags_str): 32 self._tags = tags_str.split(',') if tags_str else None 33 34 def __nonzero__(self): 35 return self._tags is not None 36 37 def HasLabelIn(self, story): 38 return self and bool(story.tags.intersection(self._tags)) 39 40 41 class StoryFilter(command_line.ArgumentHandlerMixIn): 42 """Filters stories in the story set based on command-line flags.""" 43 44 @classmethod 45 def AddCommandLineArgs(cls, parser): 46 group = optparse.OptionGroup(parser, 'User story filtering options') 47 group.add_option('--story-filter', 48 help='Use only stories whose names match the given filter regexp.') 49 group.add_option('--story-filter-exclude', 50 help='Exclude stories whose names match the given filter regexp.') 51 group.add_option('--story-tag-filter', 52 help='Use only stories that have any of these tags') 53 group.add_option('--story-tag-filter-exclude', 54 help='Exclude stories that have any of these tags') 55 parser.add_option_group(group) 56 57 @classmethod 58 def ProcessCommandLineArgs(cls, parser, args): 59 cls._include_regex = _StoryMatcher(args.story_filter) 60 cls._exclude_regex = _StoryMatcher(args.story_filter_exclude) 61 62 cls._include_tags = _StoryTagMatcher(args.story_tag_filter) 63 cls._exclude_tags = _StoryTagMatcher(args.story_tag_filter_exclude) 64 65 if cls._include_regex.has_compile_error: 66 raise parser.error('--story-filter: Invalid regex.') 67 if cls._exclude_regex.has_compile_error: 68 raise parser.error('--story-filter-exclude: Invalid regex.') 69 70 @classmethod 71 def IsSelected(cls, story): 72 # Exclude filters take priority. 73 if cls._exclude_tags.HasLabelIn(story): 74 return False 75 if cls._exclude_regex.HasMatch(story): 76 return False 77 78 if cls._include_tags and not cls._include_tags.HasLabelIn(story): 79 return False 80 if cls._include_regex and not cls._include_regex.HasMatch(story): 81 return False 82 return True 83