| OLD | NEW |
| (Empty) |
| 1 # Copyright (c) 2012 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 import inspect | |
| 5 import logging | |
| 6 import os | |
| 7 import traceback | |
| 8 | |
| 9 def Discover(start_dir, top_level_dir, suffix, clazz, | |
| 10 import_error_should_raise=False): | |
| 11 """Discover all classes in |start_dir| which subclass |clazz|. | |
| 12 | |
| 13 Args: | |
| 14 start_dir: The directory to recursively search. | |
| 15 suffix: file name suffix for files to import, without the '.py' ending. | |
| 16 clazz: The base class to search for. | |
| 17 import_error_should_raise: If false, then import errors are logged but do | |
| 18 not stop discovery. | |
| 19 | |
| 20 Returns: | |
| 21 dict of {module_name: class}. | |
| 22 """ | |
| 23 classes = {} | |
| 24 for dirpath, _, filenames in os.walk(start_dir): | |
| 25 for filename in filenames: | |
| 26 if not filename.endswith(suffix + '.py'): | |
| 27 continue | |
| 28 name, _ = os.path.splitext(filename) | |
| 29 relpath = os.path.relpath(dirpath, top_level_dir) | |
| 30 fqn = relpath.replace('/', '.') + '.' + name | |
| 31 try: | |
| 32 module = __import__(fqn, fromlist=[True]) | |
| 33 except Exception: | |
| 34 if import_error_should_raise: | |
| 35 raise | |
| 36 logging.error('While importing [%s]\n' % fqn) | |
| 37 traceback.print_exc() | |
| 38 continue | |
| 39 for name, obj in inspect.getmembers(module): | |
| 40 if inspect.isclass(obj): | |
| 41 if clazz in inspect.getmro(obj): | |
| 42 name = module.__name__.split('.')[-1] | |
| 43 classes[name] = obj | |
| 44 return classes | |
| OLD | NEW |