1*4882a593Smuzhiyun# 2*4882a593Smuzhiyun# SPDX-License-Identifier: GPL-2.0-only 3*4882a593Smuzhiyun# 4*4882a593Smuzhiyun 5*4882a593Smuzhiyunimport types 6*4882a593Smuzhiyunimport bb 7*4882a593Smuzhiyunimport os 8*4882a593Smuzhiyun 9*4882a593Smuzhiyun# This class is responsible for loading a test target controller 10*4882a593Smuzhiyunclass TestTargetLoader: 11*4882a593Smuzhiyun 12*4882a593Smuzhiyun # Search oeqa.controllers module directory for and return a controller 13*4882a593Smuzhiyun # corresponding to the given target name. 14*4882a593Smuzhiyun # AttributeError raised if not found. 15*4882a593Smuzhiyun # ImportError raised if a provided module can not be imported. 16*4882a593Smuzhiyun def get_controller_module(self, target, bbpath): 17*4882a593Smuzhiyun controllerslist = self.get_controller_modulenames(bbpath) 18*4882a593Smuzhiyun bb.note("Available controller modules: %s" % str(controllerslist)) 19*4882a593Smuzhiyun controller = self.load_controller_from_name(target, controllerslist) 20*4882a593Smuzhiyun return controller 21*4882a593Smuzhiyun 22*4882a593Smuzhiyun # Return a list of all python modules in lib/oeqa/controllers for each 23*4882a593Smuzhiyun # layer in bbpath 24*4882a593Smuzhiyun def get_controller_modulenames(self, bbpath): 25*4882a593Smuzhiyun 26*4882a593Smuzhiyun controllerslist = [] 27*4882a593Smuzhiyun 28*4882a593Smuzhiyun def add_controller_list(path): 29*4882a593Smuzhiyun if not os.path.exists(os.path.join(path, '__init__.py')): 30*4882a593Smuzhiyun bb.fatal('Controllers directory %s exists but is missing __init__.py' % path) 31*4882a593Smuzhiyun files = sorted([f for f in os.listdir(path) if f.endswith('.py') and not f.startswith('_')]) 32*4882a593Smuzhiyun for f in files: 33*4882a593Smuzhiyun module = 'oeqa.controllers.' + f[:-3] 34*4882a593Smuzhiyun if module not in controllerslist: 35*4882a593Smuzhiyun controllerslist.append(module) 36*4882a593Smuzhiyun else: 37*4882a593Smuzhiyun bb.warn("Duplicate controller module found for %s, only one added. Layers should create unique controller module names" % module) 38*4882a593Smuzhiyun 39*4882a593Smuzhiyun for p in bbpath: 40*4882a593Smuzhiyun controllerpath = os.path.join(p, 'lib', 'oeqa', 'controllers') 41*4882a593Smuzhiyun bb.debug(2, 'Searching for target controllers in %s' % controllerpath) 42*4882a593Smuzhiyun if os.path.exists(controllerpath): 43*4882a593Smuzhiyun add_controller_list(controllerpath) 44*4882a593Smuzhiyun return controllerslist 45*4882a593Smuzhiyun 46*4882a593Smuzhiyun # Search for and return a controller from given target name and 47*4882a593Smuzhiyun # set of module names. 48*4882a593Smuzhiyun # Raise AttributeError if not found. 49*4882a593Smuzhiyun # Raise ImportError if a provided module can not be imported 50*4882a593Smuzhiyun def load_controller_from_name(self, target, modulenames): 51*4882a593Smuzhiyun for name in modulenames: 52*4882a593Smuzhiyun obj = self.load_controller_from_module(target, name) 53*4882a593Smuzhiyun if obj: 54*4882a593Smuzhiyun return obj 55*4882a593Smuzhiyun raise AttributeError("Unable to load {0} from available modules: {1}".format(target, str(modulenames))) 56*4882a593Smuzhiyun 57*4882a593Smuzhiyun # Search for and return a controller or None from given module name 58*4882a593Smuzhiyun def load_controller_from_module(self, target, modulename): 59*4882a593Smuzhiyun obj = None 60*4882a593Smuzhiyun # import module, allowing it to raise import exception 61*4882a593Smuzhiyun module = __import__(modulename, globals(), locals(), [target]) 62*4882a593Smuzhiyun # look for target class in the module, catching any exceptions as it 63*4882a593Smuzhiyun # is valid that a module may not have the target class. 64*4882a593Smuzhiyun try: 65*4882a593Smuzhiyun obj = getattr(module, target) 66*4882a593Smuzhiyun if obj: 67*4882a593Smuzhiyun from oeqa.targetcontrol import BaseTarget 68*4882a593Smuzhiyun if( not issubclass(obj, BaseTarget)): 69*4882a593Smuzhiyun bb.warn("Target {0} found, but subclass is not BaseTarget".format(target)) 70*4882a593Smuzhiyun except: 71*4882a593Smuzhiyun obj = None 72*4882a593Smuzhiyun return obj 73