diff options
Diffstat (limited to 'lib/spack/spack/report.py')
-rw-r--r-- | lib/spack/spack/report.py | 160 |
1 files changed, 67 insertions, 93 deletions
diff --git a/lib/spack/spack/report.py b/lib/spack/spack/report.py index 8e50ebece6..ec81502887 100644 --- a/lib/spack/spack/report.py +++ b/lib/spack/spack/report.py @@ -20,33 +20,24 @@ from spack.reporter import Reporter from spack.reporters.cdash import CDash from spack.reporters.junit import JUnit -report_writers = { - None: Reporter, - 'junit': JUnit, - 'cdash': CDash -} +report_writers = {None: Reporter, "junit": JUnit, "cdash": CDash} #: Allowed report formats valid_formats = list(report_writers.keys()) -__all__ = [ - 'valid_formats', - 'collect_info' -] +__all__ = ["valid_formats", "collect_info"] def fetch_log(pkg, do_fn, dir): log_files = { - '_install_task': pkg.build_log_path, - 'do_test': os.path.join(dir, TestSuite.test_log_name(pkg.spec)), + "_install_task": pkg.build_log_path, + "do_test": os.path.join(dir, TestSuite.test_log_name(pkg.spec)), } try: - with codecs.open(log_files[do_fn.__name__], 'r', 'utf-8') as f: - return ''.join(f.readlines()) + with codecs.open(log_files[do_fn.__name__], "r", "utf-8") as f: + return "".join(f.readlines()) except Exception: - return 'Cannot open log for {0}'.format( - pkg.spec.cshort_spec - ) + return "Cannot open log for {0}".format(pkg.spec.cshort_spec) class InfoCollector(object): @@ -64,6 +55,7 @@ class InfoCollector(object): specs (list of Spec): specs whose install information will be recorded """ + def __init__(self, wrap_class, do_fn, specs, dir): #: Class for which to wrap a function self.wrap_class = wrap_class @@ -82,44 +74,38 @@ class InfoCollector(object): def __enter__(self): # Initialize the spec report with the data that is available upfront. for input_spec in self.input_specs: - name_fmt = '{0}_{1}' - name = name_fmt.format(input_spec.name, - input_spec.dag_hash(length=7)) + name_fmt = "{0}_{1}" + name = name_fmt.format(input_spec.name, input_spec.dag_hash(length=7)) spec = { - 'name': name, - 'nerrors': None, - 'nfailures': None, - 'npackages': None, - 'time': None, - 'timestamp': time.strftime( - "%a, %d %b %Y %H:%M:%S", time.gmtime() - ), - 'properties': [], - 'packages': [] + "name": name, + "nerrors": None, + "nfailures": None, + "npackages": None, + "time": None, + "timestamp": time.strftime("%a, %d %b %Y %H:%M:%S", time.gmtime()), + "properties": [], + "packages": [], } self.specs.append(spec) - Property = collections.namedtuple('Property', ['name', 'value']) - spec['properties'].append( - Property('architecture', input_spec.architecture) - ) - spec['properties'].append( - Property('compiler', input_spec.compiler)) + Property = collections.namedtuple("Property", ["name", "value"]) + spec["properties"].append(Property("architecture", input_spec.architecture)) + spec["properties"].append(Property("compiler", input_spec.compiler)) # Check which specs are already installed and mark them as skipped # only for install_task - if self.do_fn == '_install_task': + if self.do_fn == "_install_task": for dep in filter(lambda x: x.installed, input_spec.traverse()): package = { - 'name': dep.name, - 'id': dep.dag_hash(), - 'elapsed_time': '0.0', - 'result': 'skipped', - 'message': 'Spec already installed' + "name": dep.name, + "id": dep.dag_hash(), + "elapsed_time": "0.0", + "result": "skipped", + "message": "Spec already installed", } - spec['packages'].append(package) + spec["packages"].append(package) def gather_info(do_fn): """Decorates do_fn to gather useful information for @@ -128,11 +114,12 @@ class InfoCollector(object): It's defined here to capture the environment and build this context as the installations proceed. """ + @functools.wraps(do_fn) def wrapper(instance, *args, **kwargs): if isinstance(instance, spack.package_base.PackageBase): pkg = instance - elif hasattr(args[0], 'pkg'): + elif hasattr(args[0], "pkg"): pkg = args[0].pkg else: raise Exception @@ -141,12 +128,12 @@ class InfoCollector(object): installed_already = pkg.spec.installed package = { - 'name': pkg.name, - 'id': pkg.spec.dag_hash(), - 'elapsed_time': None, - 'result': None, - 'message': None, - 'installed_from_binary_cache': False + "name": pkg.name, + "id": pkg.spec.dag_hash(), + "elapsed_time": None, + "result": None, + "message": None, + "installed_from_binary_cache": False, } # Append the package to the correct spec report. In some @@ -157,11 +144,8 @@ class InfoCollector(object): for s in llnl.util.lang.dedupe([pkg.spec.root, pkg.spec]): name = name_fmt.format(s.name, s.dag_hash(length=7)) try: - item = next(( - x for x in self.specs - if x['name'] == name - )) - item['packages'].append(package) + item = next((x for x in self.specs if x["name"] == name)) + item["packages"].append(package) except StopIteration: pass @@ -170,47 +154,44 @@ class InfoCollector(object): try: value = do_fn(instance, *args, **kwargs) - externals = kwargs.get('externals', False) + externals = kwargs.get("externals", False) skip_externals = pkg.spec.external and not externals - if do_fn.__name__ == 'do_test' and skip_externals: - package['result'] = 'skipped' + if do_fn.__name__ == "do_test" and skip_externals: + package["result"] = "skipped" else: - package['result'] = 'success' - package['stdout'] = fetch_log(pkg, do_fn, self.dir) - package['installed_from_binary_cache'] = \ - pkg.installed_from_binary_cache - if do_fn.__name__ == '_install_task' and installed_already: + package["result"] = "success" + package["stdout"] = fetch_log(pkg, do_fn, self.dir) + package["installed_from_binary_cache"] = pkg.installed_from_binary_cache + if do_fn.__name__ == "_install_task" and installed_already: return except spack.build_environment.InstallError as e: # An InstallError is considered a failure (the recipe # didn't work correctly) - package['result'] = 'failure' - package['message'] = e.message or 'Installation failure' - package['stdout'] = fetch_log(pkg, do_fn, self.dir) - package['stdout'] += package['message'] - package['exception'] = e.traceback + package["result"] = "failure" + package["message"] = e.message or "Installation failure" + package["stdout"] = fetch_log(pkg, do_fn, self.dir) + package["stdout"] += package["message"] + package["exception"] = e.traceback raise except (Exception, BaseException) as e: # Everything else is an error (the installation # failed outside of the child process) - package['result'] = 'error' - package['stdout'] = fetch_log(pkg, do_fn, self.dir) - package['message'] = str(e) or 'Unknown error' - package['exception'] = traceback.format_exc() + package["result"] = "error" + package["stdout"] = fetch_log(pkg, do_fn, self.dir) + package["message"] = str(e) or "Unknown error" + package["exception"] = traceback.format_exc() raise finally: - package['elapsed_time'] = time.time() - start_time + package["elapsed_time"] = time.time() - start_time return value return wrapper - setattr(self.wrap_class, self.do_fn, gather_info( - getattr(self.wrap_class, self.do_fn) - )) + setattr(self.wrap_class, self.do_fn, gather_info(getattr(self.wrap_class, self.do_fn))) def __exit__(self, exc_type, exc_val, exc_tb): @@ -218,16 +199,10 @@ class InfoCollector(object): setattr(self.wrap_class, self.do_fn, self._backup_do_fn) for spec in self.specs: - spec['npackages'] = len(spec['packages']) - spec['nfailures'] = len( - [x for x in spec['packages'] if x['result'] == 'failure'] - ) - spec['nerrors'] = len( - [x for x in spec['packages'] if x['result'] == 'error'] - ) - spec['time'] = sum([ - float(x['elapsed_time']) for x in spec['packages'] - ]) + spec["npackages"] = len(spec["packages"]) + spec["nfailures"] = len([x for x in spec["packages"] if x["result"] == "failure"]) + spec["nerrors"] = len([x for x in spec["packages"] if x["result"] == "error"]) + spec["time"] = sum([float(x["elapsed_time"]) for x in spec["packages"]]) class collect_info(object): @@ -265,19 +240,19 @@ class collect_info(object): Raises: ValueError: when ``format_name`` is not in ``valid_formats`` """ + def __init__(self, cls, function, format_name, args): self.cls = cls self.function = function self.filename = None if args.cdash_upload_url: - self.format_name = 'cdash' - self.filename = 'cdash_report' + self.format_name = "cdash" + self.filename = "cdash_report" else: self.format_name = format_name # Check that the format is valid. if self.format_name not in valid_formats: - raise ValueError('invalid report type: {0}' - .format(self.format_name)) + raise ValueError("invalid report type: {0}".format(self.format_name)) self.report_writer = report_writers[self.format_name](args) def __call__(self, type, dir=None): @@ -291,8 +266,7 @@ class collect_info(object): def __enter__(self): if self.format_name: # Start the collector and patch self.function on appropriate class - self.collector = InfoCollector( - self.cls, self.function, self.specs, self.dir) + self.collector = InfoCollector(self.cls, self.function, self.specs, self.dir) self.collector.__enter__() def __exit__(self, exc_type, exc_val, exc_tb): @@ -301,6 +275,6 @@ class collect_info(object): # original PackageInstaller._install_task self.collector.__exit__(exc_type, exc_val, exc_tb) - report_data = {'specs': self.collector.specs} - report_fn = getattr(self.report_writer, '%s_report' % self.type) + report_data = {"specs": self.collector.specs} + report_fn = getattr(self.report_writer, "%s_report" % self.type) report_fn(self.filename, report_data) |