Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(915)

Unified Diff: telemetry/telemetry/core/discover.py

Issue 2941123002: [Telemetry] Move discover to common/py_utils (Closed)
Patch Set: fix imports Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « telemetry/telemetry/benchmark_runner.py ('k') | telemetry/telemetry/core/discover_unittest.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: telemetry/telemetry/core/discover.py
diff --git a/telemetry/telemetry/core/discover.py b/telemetry/telemetry/core/discover.py
index 7e7e4306ef33c717d0ec88cf14c98761f8ce4c22..91a59a02457b782f2ecf8ee7b0bcaaa9270dba64 100644
--- a/telemetry/telemetry/core/discover.py
+++ b/telemetry/telemetry/core/discover.py
@@ -1,190 +1,10 @@
-# Copyright 2012 The Chromium Authors. All rights reserved.
+# Copyright 2017 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-import fnmatch
-import inspect
-import os
-import re
-import sys
+"""Shim for discover; will be removed once #3612 is fixed."""
-from py_utils import camel_case
+from py_utils import discover
-
-def DiscoverModules(start_dir, top_level_dir, pattern='*'):
- """Discover all modules in |start_dir| which match |pattern|.
-
- Args:
- start_dir: The directory to recursively search.
- top_level_dir: The top level of the package, for importing.
- pattern: Unix shell-style pattern for filtering the filenames to import.
-
- Returns:
- list of modules.
- """
- # start_dir and top_level_dir must be consistent with each other.
- start_dir = os.path.realpath(start_dir)
- top_level_dir = os.path.realpath(top_level_dir)
-
- modules = []
- sub_paths = list(os.walk(start_dir))
- # We sort the directories & file paths to ensure a deterministic ordering when
- # traversing |top_level_dir|.
- sub_paths.sort(key=lambda paths_tuple: paths_tuple[0])
- for dir_path, _, filenames in sub_paths:
- # Sort the directories to walk recursively by the directory path.
- filenames.sort()
- for filename in filenames:
- # Filter out unwanted filenames.
- if filename.startswith('.') or filename.startswith('_'):
- continue
- if os.path.splitext(filename)[1] != '.py':
- continue
- if not fnmatch.fnmatch(filename, pattern):
- continue
-
- # Find the module.
- module_rel_path = os.path.relpath(
- os.path.join(dir_path, filename), top_level_dir)
- module_name = re.sub(r'[/\\]', '.', os.path.splitext(module_rel_path)[0])
-
- # Import the module.
- try:
- # Make sure that top_level_dir is the first path in the sys.path in case
- # there are naming conflict in module parts.
- original_sys_path = sys.path[:]
- sys.path.insert(0, top_level_dir)
- module = __import__(module_name, fromlist=[True])
- modules.append(module)
- finally:
- sys.path = original_sys_path
- return modules
-
-
-def AssertNoKeyConflicts(classes_by_key_1, classes_by_key_2):
- for k in classes_by_key_1:
- if k in classes_by_key_2:
- assert classes_by_key_1[k] is classes_by_key_2[k], (
- 'Found conflicting classes for the same key: '
- 'key=%s, class_1=%s, class_2=%s' % (
- k, classes_by_key_1[k], classes_by_key_2[k]))
-
-
-# TODO(dtu): Normalize all discoverable classes to have corresponding module
-# and class names, then always index by class name.
-def DiscoverClasses(start_dir,
- top_level_dir,
- base_class,
- pattern='*',
- 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.
-
- Args:
- start_dir: The directory to recursively search.
- 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.
- 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:
- dict of {module_name: class} or {underscored_class_name: class}
- """
- modules = DiscoverModules(start_dir, top_level_dir, pattern)
- classes = {}
- for module in modules:
- new_classes = DiscoverClassesInModule(
- module, base_class, index_by_class_name, directly_constructable)
- # TODO(nednguyen): we should remove index_by_class_name once
- # benchmark_smoke_unittest in chromium/src/tools/perf no longer relied
- # naming collisions to reduce the number of smoked benchmark tests.
- # crbug.com/548652
- if index_by_class_name:
- AssertNoKeyConflicts(classes, new_classes)
- classes = dict(classes.items() + new_classes.items())
- return classes
-
-
-# TODO(nednguyen): we should remove index_by_class_name once
-# benchmark_smoke_unittest in chromium/src/tools/perf no longer relied
-# naming collisions to reduce the number of smoked benchmark tests.
-# crbug.com/548652
-def DiscoverClassesInModule(module,
- base_class,
- index_by_class_name=False,
- directly_constructable=False):
- """Discover all classes in |module| which subclass |base_class|.
-
- Base classes that contain subclasses are ignored by default.
-
- Args:
- module: The module to search.
- base_class: The base class to search for.
- index_by_class_name: If True, use class name converted to
- lowercase_with_underscores instead of module name in return dict keys.
-
- Returns:
- dict of {module_name: class} or {underscored_class_name: class}
- """
- classes = {}
- for _, obj in inspect.getmembers(module):
- # Ensure object is a class.
- if not inspect.isclass(obj):
- continue
- # Include only subclasses of base_class.
- if not issubclass(obj, base_class):
- continue
- # Exclude the base_class itself.
- if obj is base_class:
- continue
- # Exclude protected or private classes.
- if obj.__name__.startswith('_'):
- continue
- # Include only the module in which the class is defined.
- # If a class is imported by another module, exclude those duplicates.
- 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 IsDirectlyConstructable(obj):
- if key_name in classes and index_by_class_name:
- assert classes[key_name] is obj, (
- 'Duplicate key_name with different objs detected: '
- 'key=%s, obj1=%s, obj2=%s' % (key_name, classes[key_name], obj))
- else:
- classes[key_name] = obj
-
- return classes
-
-
-def IsDirectlyConstructable(cls):
- """Returns True if instance of |cls| can be construct without arguments."""
- assert inspect.isclass(cls)
- if not hasattr(cls, '__init__'):
- # Case |class A: pass|.
- return True
- if cls.__init__ is object.__init__:
- # Case |class A(object): pass|.
- return True
- # Case |class (object):| with |__init__| other than |object.__init__|.
- args, _, _, defaults = inspect.getargspec(cls.__init__)
- if defaults is None:
- defaults = ()
- # Return true if |self| is only arg without a default.
- return len(args) == len(defaults) + 1
-
-
-_counter = [0]
-
-
-def _GetUniqueModuleName():
- _counter[0] += 1
- return "module_" + str(_counter[0])
+DiscoverClasses = discover.DiscoverClasses
+DiscoverClassesInModule = discover.DiscoverClassesInModule
« no previous file with comments | « telemetry/telemetry/benchmark_runner.py ('k') | telemetry/telemetry/core/discover_unittest.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698