1*9c5db199SXin Li# Lint as: python2, python3 2*9c5db199SXin Lifrom __future__ import absolute_import 3*9c5db199SXin Lifrom __future__ import division 4*9c5db199SXin Lifrom __future__ import print_function 5*9c5db199SXin Liimport itertools 6*9c5db199SXin Liimport common 7*9c5db199SXin Liimport six 8*9c5db199SXin Li 9*9c5db199SXin Li 10*9c5db199SXin Lidef _get_unpassable_types(arg): 11*9c5db199SXin Li """ Given an argument, returns a set of types contained in arg that are 12*9c5db199SXin Li unpassable. If arg is an atomic type (e.g. int) it either returns an 13*9c5db199SXin Li empty set (if the type is passable) or a singleton of the type (if the 14*9c5db199SXin Li type is not passable). """ 15*9c5db199SXin Li if isinstance(arg, (six.string_types, int, int)): 16*9c5db199SXin Li return set() 17*9c5db199SXin Li elif isinstance(arg, (list, tuple, set, frozenset, dict)): 18*9c5db199SXin Li if isinstance(arg, dict): 19*9c5db199SXin Li # keys and values must both be passable 20*9c5db199SXin Li parts = itertools.chain(six.iterkeys(arg), six.itervalues(arg)) 21*9c5db199SXin Li else: 22*9c5db199SXin Li # for all other containers we just iterate 23*9c5db199SXin Li parts = iter(arg) 24*9c5db199SXin Li types = set() 25*9c5db199SXin Li for part in parts: 26*9c5db199SXin Li types |= _get_unpassable_types(part) 27*9c5db199SXin Li return types 28*9c5db199SXin Li else: 29*9c5db199SXin Li return set([type(arg)]) 30*9c5db199SXin Li 31*9c5db199SXin Li 32*9c5db199SXin Lidef _validate_args(args): 33*9c5db199SXin Li """ Validates arguments. Lists and dictionaries are valid argument types, 34*9c5db199SXin Li so you can pass *args and **dargs in directly, rather than having to 35*9c5db199SXin Li iterate over them yourself. """ 36*9c5db199SXin Li unpassable_types = _get_unpassable_types(args) 37*9c5db199SXin Li if unpassable_types: 38*9c5db199SXin Li msg = "arguments of type '%s' cannot be passed to remote profilers" 39*9c5db199SXin Li msg %= ", ".join(t.__name__ for t in unpassable_types) 40*9c5db199SXin Li raise TypeError(msg) 41*9c5db199SXin Li 42*9c5db199SXin Li 43*9c5db199SXin Liclass profiler_proxy(object): 44*9c5db199SXin Li """ This is a server-side class that acts as a proxy to a real client-side 45*9c5db199SXin Li profiler class.""" 46*9c5db199SXin Li 47*9c5db199SXin Li def __init__(self, profiler_name): 48*9c5db199SXin Li self.name = profiler_name 49*9c5db199SXin Li 50*9c5db199SXin Li # does the profiler support rebooting? 51*9c5db199SXin Li profiler_module = common.setup_modules.import_module( 52*9c5db199SXin Li profiler_name, "autotest_lib.client.profilers.%s" % profiler_name) 53*9c5db199SXin Li profiler_class = getattr(profiler_module, profiler_name) 54*9c5db199SXin Li self.supports_reboot = profiler_class.supports_reboot 55*9c5db199SXin Li 56*9c5db199SXin Li 57*9c5db199SXin Li def initialize(self, *args, **dargs): 58*9c5db199SXin Li _validate_args(args) 59*9c5db199SXin Li _validate_args(dargs) 60*9c5db199SXin Li self.args, self.dargs = args, dargs 61*9c5db199SXin Li 62*9c5db199SXin Li 63*9c5db199SXin Li def setup(self, *args, **dargs): 64*9c5db199SXin Li assert self.args == args and self.dargs == dargs 65*9c5db199SXin Li # the actual setup happens lazily at start() 66*9c5db199SXin Li 67*9c5db199SXin Li 68*9c5db199SXin Li def start(self, test, host=None): 69*9c5db199SXin Li raise NotImplementedError('start not implemented') 70*9c5db199SXin Li 71*9c5db199SXin Li 72*9c5db199SXin Li def stop(self, test, host=None): 73*9c5db199SXin Li raise NotImplementedError('stop not implemented') 74*9c5db199SXin Li 75*9c5db199SXin Li 76*9c5db199SXin Li def report(self, test, host=None, wait_on_client=True): 77*9c5db199SXin Li raise NotImplementedError('report not implemented') 78