diff --git a/wa/framework/getters.py b/wa/framework/getters.py index e2ca572c..e4572070 100644 --- a/wa/framework/getters.py +++ b/wa/framework/getters.py @@ -71,6 +71,14 @@ def get_generic_resource(resource, files): return matches[0] +def get_path_matches(resource, files): + matches = [] + for f in files: + if resource.match_path(f): + matches.append(f) + return matches + + def get_from_location(basepath, resource): if resource.kind == 'file': path = os.path.join(basepath, resource.path) @@ -204,10 +212,15 @@ class Http(ResourceGetter): return # TODO: add support for unowned resources if not self.index: self.index = self.fetch_index() - asset = self.resolve_resource(resource) - if not asset: - return - return self.download_asset(asset, resource.owner.name) + if resource.kind == 'apk': + # APKs must always be downloaded to run ApkInfo for version + # information. + return self.resolve_apk(resource) + else: + asset = self.resolve_resource(resource) + if not asset: + return + return self.download_asset(asset, resource.owner.name) def fetch_index(self): if not self.url: @@ -251,6 +264,20 @@ class Http(ResourceGetter): auth = None return requests.get(url, auth=auth, stream=stream) + def resolve_apk(self, resource): + assets = self.index.get(resource.owner.name, {}) + if not assets: + return None + asset_map = {a['path']: a for a in assets} + paths = get_path_matches(resource, asset_map.keys()) + local_paths = [] + for path in paths: + local_paths.append(self.download_asset(asset_map[path], + resource.owner.name)) + for path in local_paths: + if resource.match(path): + return path + def resolve_resource(self, resource): # pylint: disable=too-many-branches,too-many-locals assets = self.index.get(resource.owner.name, {}) @@ -258,13 +285,7 @@ class Http(ResourceGetter): return {} asset_map = {a['path']: a for a in assets} - if resource.kind in ['apk', 'jar', 'revent']: - if resource.kind == 'apk' and resource.version: - # TODO: modify the index format to attach version info to the - # APK entries. - msg = 'Versions of APKs cannot be fetched over HTTP at this time' - self.logger.warning(msg) - return {} + if resource.kind in ['jar', 'revent']: path = get_generic_resource(resource, asset_map.keys()) if path: return asset_map[path] diff --git a/wa/framework/resource.py b/wa/framework/resource.py index ec8d36bc..b137fae9 100644 --- a/wa/framework/resource.py +++ b/wa/framework/resource.py @@ -72,6 +72,9 @@ class Resource(object): self.owner = owner def match(self, path): + return self.match_path(path) + + def match_path(self, path): raise NotImplementedError() def __str__(self): @@ -86,7 +89,7 @@ class File(Resource): super(File, self).__init__(owner) self.path = path - def match(self, path): + def match_path(self, path): return self.path == path def __str__(self): @@ -102,7 +105,7 @@ class Executable(Resource): self.abi = abi self.filename = filename - def match(self, path): + def match_path(self, path): return self.filename == os.path.basename(path) def __str__(self): @@ -118,7 +121,7 @@ class ReventFile(Resource): self.stage = stage self.target = target - def match(self, path): + def match_path(self, path): filename = os.path.basename(path) parts = filename.split('.') if len(parts) > 2: @@ -133,7 +136,7 @@ class JarFile(Resource): kind = 'jar' - def match(self, path): + def match_path(self, path): # An owner always has at most one jar file, so # always match return True @@ -154,6 +157,10 @@ class ApkFile(Resource): self.exact_abi = exact_abi self.supported_abi = supported_abi + def match_path(self, path): + ext = os.path.splitext(path)[1].lower() + return ext == '.apk' + def match(self, path): name_matches = True version_matches = True diff --git a/wa/instrumentation/energy_measurement.py b/wa/instrumentation/energy_measurement.py index 95fcad02..d4d77c76 100644 --- a/wa/instrumentation/energy_measurement.py +++ b/wa/instrumentation/energy_measurement.py @@ -30,7 +30,7 @@ from wa import Instrument, Parameter from wa.framework import pluginloader from wa.framework.plugin import Plugin from wa.framework.exception import ConfigError, InstrumentError -from wa.utils.types import list_of_strings, list_of_ints, list_or_string, obj_dict +from wa.utils.types import list_of_strings, list_of_ints, list_or_string, obj_dict, identifier class EnergyInstrumentBackend(Plugin): @@ -249,10 +249,15 @@ class EnergyMeasurement(Instrument): self.backend = self.loader.get_plugin(self.instrument) self.params = obj_dict() + instrument_parameters = {identifier(k): v + for k, v in self.instrument_parameters.iteritems()} supported_params = self.backend.get_parameters() for name, param in supported_params.iteritems(): - value = self.instrument_parameters.get(name) + value = instrument_parameters.pop(name, None) param.set_value(self.params, value) + if instrument_parameters: + msg = 'Unexpected parameters for backend "{}": {}' + raise ConfigError(msg.format(self.instrument, instrument_parameters)) self.backend.validate_parameters(self.params) def initialize(self, context):