Index: tools/telemetry/telemetry/core/discover.py |
diff --git a/tools/telemetry/telemetry/core/discover.py b/tools/telemetry/telemetry/core/discover.py |
index 53393200acea97da5606898005e0efd6d93d5f35..546aa6372327899f6fa4e8535dba88010d4eeaef 100644 |
--- a/tools/telemetry/telemetry/core/discover.py |
+++ b/tools/telemetry/telemetry/core/discover.py |
@@ -7,9 +7,12 @@ |
import os |
import re |
+from telemetry import decorators |
+from telemetry.internal.util import camel_case |
from telemetry.internal.util import classes as classes_module |
+@decorators.Cache |
def DiscoverModules(start_dir, top_level_dir, pattern='*'): |
"""Discover all modules in |start_dir| which match |pattern|. |
@@ -46,8 +49,12 @@ |
modules.append(module) |
return modules |
+ |
+# TODO(dtu): Normalize all discoverable classes to have corresponding module |
+# and class names, then always index by class name. |
+@decorators.Cache |
def DiscoverClasses(start_dir, top_level_dir, base_class, pattern='*', |
- one_class_per_module=False, directly_constructable=False): |
+ index_by_class_name=True, directly_constructable=False): |
"""Discover all classes in |start_dir| which subclass |base_class|. |
Base classes that contain subclasses are ignored by default. |
@@ -57,21 +64,24 @@ |
top_level_dir: The top level of the package, for importing. |
base_class: The base class to search for. |
pattern: Unix shell-style pattern for filtering the filenames to import. |
- one_class_per_module: If True, will only include the first class found in |
- each module. |
+ index_by_class_name: If True, use class name converted to |
+ lowercase_with_underscores instead of module name in return dict keys. |
directly_constructable: If True, will only return classes that can be |
constructed without arguments |
- Returns: A list of classes. |
+ Returns: |
+ dict of {module_name: class} or {underscored_class_name: class} |
""" |
modules = DiscoverModules(start_dir, top_level_dir, pattern) |
- classes = [] |
+ classes = {} |
for module in modules: |
- classes.extend(DiscoverClassesInModule( |
- module, base_class, one_class_per_module, directly_constructable)) |
+ new_classes = DiscoverClassesInModule( |
+ module, base_class, index_by_class_name, directly_constructable) |
+ classes = dict(classes.items() + new_classes.items()) |
return classes |
-def DiscoverClassesInModule(module, base_class, one_class_per_module=False, |
+@decorators.Cache |
+def DiscoverClassesInModule(module, base_class, index_by_class_name=False, |
directly_constructable=False): |
"""Discover all classes in |module| which subclass |base_class|. |
@@ -80,12 +90,13 @@ |
Args: |
module: The module to search. |
base_class: The base class to search for. |
- one_class_per_module: If True, will only include the first class found in |
- each module. |
+ index_by_class_name: If True, use class name converted to |
+ lowercase_with_underscores instead of module name in return dict keys. |
- Returns: A list of classes. |
+ Returns: |
+ dict of {module_name: class} or {underscored_class_name: class} |
""" |
- classes = [] |
+ classes = {} |
for _, obj in inspect.getmembers(module): |
# Ensure object is a class. |
if not inspect.isclass(obj): |
@@ -104,11 +115,14 @@ |
if obj.__module__ != module.__name__: |
continue |
+ if index_by_class_name: |
+ key_name = camel_case.ToUnderscore(obj.__name__) |
+ else: |
+ key_name = module.__name__.split('.')[-1] |
if (not directly_constructable or |
classes_module.IsDirectlyConstructable(obj)): |
- classes.append(obj) |
- if one_class_per_module: |
- return classes |
+ classes[key_name] = obj |
+ |
return classes |