1# Copyright (c) 2013 The Chromium OS 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 5import logging 6import pprint 7 8import common 9from autotest_lib.server.cros.faft.config import DEFAULTS 10 11 12class Config(object): 13 """Configuration for FAFT tests. 14 15 This object is meant to be the interface to all configuration required 16 by FAFT tests, including device specific overrides. 17 18 It gets the default values from DEFAULTS.py which is found within 19 the config package and the overrides come from module files named 20 the same (Link.py, ...) as the value passed in via 21 'platform' (e.g. Link, Stumpy, ...). Note we consider the platform name 22 case insensitive and by convention platform override files should be 23 lowercase. 24 25 The DEFAULTS module must exist and contain a class named 'Values'. 26 27 The override module is optional. If it exists, it must contain a 'Values' 28 class. That class can inherit any other override's Values class. 29 30 Attribute requests will first be searched through the overrides (if it 31 exists) and then through the defaults. 32 33 @attribute platform: string containing the platform name being tested. 34 """ 35 36 def __init__(self, platform=None): 37 """Initialize an object with FAFT settings. 38 39 Initialize a list of objects that will be searched, in order, for 40 the requested config attribute. 41 42 @param platform: string containing the platform name being tested. 43 """ 44 self.platform = platform 45 # Defaults must always exist. 46 self._precedence_list = [DEFAULTS.Values()] 47 # Overrides are optional, and not an error. 48 try: 49 config_name = platform.rsplit('_', 1)[-1].lower().replace("-", "_") 50 overrides = __import__(config_name, globals(), locals()) 51 overrides = overrides.Values() 52 # Add overrides to the first position in the list 53 self._precedence_list.insert(0, overrides) 54 except ImportError: 55 logging.debug("No config overrides found for platform: %s.", 56 platform) 57 logging.debug(str(self)) 58 59 def __getattr__(self, name): 60 """Search through every object (first in overrides then in defaults) 61 for the first occurrence of the requested attribute (name) and 62 return that. Else raise AttributeError. 63 64 @param name: string with attribute being searched for. Should not be 65 an empty string or None. 66 """ 67 for cfg_obj in self._precedence_list: 68 if hasattr(cfg_obj, name): 69 return getattr(cfg_obj, name) 70 raise AttributeError("No value exists for attribute (%s)" % name) 71 72 def _filtered_attribute_list(self): 73 """Return a sorted(set) containing all attributes from all objects with 74 attributes starting with __ being filtered out.""" 75 filtered_attributes = set() 76 for cfg_obj in self._precedence_list: 77 filtered_attributes.update([name for name in dir(cfg_obj) if 78 not name.startswith('__')]) 79 return sorted(filtered_attributes) 80 81 def __str__(self): 82 str_list = [] 83 str_list.append("--[ Raw FAFT Config Dump ]--------------------------") 84 for cfg_obj in self._precedence_list: 85 str_list.append("%s -> %s\n" % (cfg_obj, 86 pprint.pformat(dir(cfg_obj)))) 87 str_list.append("--[ Resolved FAFT Config Values ]-------------------") 88 for attr in self._filtered_attribute_list(): 89 str_list.append("%s = %s" % (attr, getattr(self, attr))) 90 str_list.append("---------------------------------------------------") 91 return "\n".join(str_list) 92