Home | History | Annotate | Download | only in story
      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 _StoryLabelMatcher(object):
     31   def __init__(self, labels_str):
     32     self._labels = labels_str.split(',') if labels_str else None
     33 
     34   def __nonzero__(self):
     35     return self._labels is not None
     36 
     37   def HasLabelIn(self, story):
     38     return self and bool(story.labels.intersection(self._labels))
     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-label-filter',
     52         help='Use only stories that have any of these labels')
     53     group.add_option('--story-label-filter-exclude',
     54         help='Exclude stories that have any of these labels')
     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     cls._include_labels = _StoryLabelMatcher(args.story_label_filter)
     62     cls._exclude_labels = _StoryLabelMatcher(args.story_label_filter_exclude)
     63 
     64     if cls._include_regex.has_compile_error:
     65       raise parser.error('--story-filter: Invalid regex.')
     66     if cls._exclude_regex.has_compile_error:
     67       raise parser.error('--story-filter-exclude: Invalid regex.')
     68 
     69   @classmethod
     70   def IsSelected(cls, story):
     71     # Exclude filters take priority.
     72     if cls._exclude_labels.HasLabelIn(story):
     73       return False
     74     if cls._exclude_regex.HasMatch(story):
     75       return False
     76 
     77     if cls._include_labels and not cls._include_labels.HasLabelIn(story):
     78       return False
     79     if cls._include_regex and not cls._include_regex.HasMatch(story):
     80       return False
     81     return True
     82