Chromium Code Reviews| Index: tools/telemetry/telemetry/core/discover.py | 
| diff --git a/tools/telemetry/telemetry/core/discover.py b/tools/telemetry/telemetry/core/discover.py | 
| index 9e8118a731fd59e29f834043096b5438750eb694..9ef13cf8bd366e904ac37cce3a374dc558643b01 100644 | 
| --- a/tools/telemetry/telemetry/core/discover.py | 
| +++ b/tools/telemetry/telemetry/core/discover.py | 
| @@ -6,11 +6,16 @@ import fnmatch | 
| import inspect | 
| import os | 
| import re | 
| +import sys | 
| from telemetry import decorators | 
| from telemetry.core import camel_case | 
| +from telemetry.core import environment | 
| from telemetry.core import util | 
| from telemetry.page import page_set | 
| +from telemetry.page import profile_creator | 
| + | 
| +config = environment.Environment([util.GetBaseDir()]) | 
| 
 
nednguyen
2014/09/04 03:31:37
Why do we need a global?
 
 | 
| @decorators.Cache | 
| @@ -133,3 +138,67 @@ def IsPageSetFile(file_path): | 
| return False | 
| module = util.GetPythonPageSetModule(file_path) | 
| return bool(DiscoverClassesInModule(module, page_set.PageSet)) | 
| + | 
| + | 
| +@decorators.Cache | 
| +def GetValidSubclassesOfClasses(base_classes, base_dir=None): | 
| 
 
nednguyen
2014/09/04 03:31:37
Please add docstring for this function and the one
 
 | 
| + classes = [] | 
| + for base_class in base_classes: | 
| + paths = config.base_paths if base_dir is None else [base_dir] | 
| + for base_dir in paths: | 
| + classes += DiscoverClasses(base_dir, base_dir, base_class, | 
| + index_by_class_name=True).values() | 
| + return [cls for cls in classes | 
| + if not issubclass(cls, profile_creator.ProfileCreator)] | 
| + | 
| + | 
| +def MatchName(base_classes, input_name, exact_matches=True, base_dir=None): | 
| + def _Matches(input_string, search_string): | 
| + if search_string.startswith(input_string): | 
| + return True | 
| + for part in search_string.split('.'): | 
| + if part.startswith(input_string): | 
| + return True | 
| + return False | 
| + | 
| + # Exact matching. | 
| + if exact_matches: | 
| + # Don't add aliases to search dict, only allow exact matching for them. | 
| + if input_name in config.test_aliases: | 
| + exact_match = config.test_aliases[input_name] | 
| + else: | 
| + exact_match = input_name | 
| + | 
| + for test_class in GetValidSubclassesOfClasses(base_classes, base_dir): | 
| + if exact_match == test_class.Name(): | 
| + return [test_class] | 
| + | 
| + # Fuzzy matching. | 
| + return [test_class for test_class in GetValidSubclassesOfClasses(base_classes, | 
| + base_dir) | 
| + if _Matches(input_name, test_class.Name())] | 
| + | 
| + | 
| +def PrintAvailableClasses(base_classes, class_list=None, | 
| + output_stream=sys.stdout): | 
| 
 
nednguyen
2014/09/04 03:31:37
Can we split this function to two functions: one t
 
 | 
| + if class_list is None: | 
| + class_list = GetValidSubclassesOfClasses(base_classes) | 
| + | 
| + if not class_list: | 
| + sys.stderr.write('No tests found!\n') | 
| + return | 
| + | 
| + # Align the class names to the longest one. | 
| + format_string = ' %%-%ds %%s' % max(len(cls.Name()) for cls in class_list) | 
| + | 
| + output = [] | 
| + for base_class in base_classes: | 
| + classes = [cls for cls in class_list if issubclass(cls, base_class)] | 
| + if classes: | 
| + output.append('Available %ss are:' % base_class.Name()) | 
| + sorted_classes = sorted(classes, key=lambda c: c.Name()) | 
| + formatted_classes = map( | 
| + lambda c: format_string % (c.Name(), c.Description()), sorted_classes) | 
| + output.extend(formatted_classes) | 
| + output.append('') | 
| + output_stream.write('\n'.join(output)) |