From bf028990e70927872cf506cf88bbf5a927ced2c4 Mon Sep 17 00:00:00 2001 From: Todd Gamblin Date: Fri, 27 May 2016 21:20:40 -0500 Subject: Make ProviderIndex yaml-izable. - allow a provider index to be stored and re-read. --- lib/spack/spack/repository.py | 1 + lib/spack/spack/test/__init__.py | 52 ++++++++++++++++++++++++++++++------- lib/spack/spack/test/virtual.py | 43 +++++++++++++++++++++++++++++++ lib/spack/spack/virtual.py | 55 +++++++++++++++++++++++++++++++++++++--- 4 files changed, 138 insertions(+), 13 deletions(-) create mode 100644 lib/spack/spack/test/virtual.py (limited to 'lib') diff --git a/lib/spack/spack/repository.py b/lib/spack/spack/repository.py index ae9fd7bee6..bf0dac6a22 100644 --- a/lib/spack/spack/repository.py +++ b/lib/spack/spack/repository.py @@ -51,6 +51,7 @@ repo_namespace = 'spack.pkg' # These names describe how repos should be laid out in the filesystem. # repo_config_name = 'repo.yaml' # Top-level filename for repo config. +repo_index_name = 'index.yaml' # Top-level filename for repository index. packages_dir_name = 'packages' # Top-level repo directory containing pkgs. package_file_name = 'package.py' # Filename for packages in a repository. diff --git a/lib/spack/spack/test/__init__.py b/lib/spack/spack/test/__init__.py index 3439764ee6..11f7298c04 100644 --- a/lib/spack/spack/test/__init__.py +++ b/lib/spack/spack/test/__init__.py @@ -33,15 +33,49 @@ from spack.test.tally_plugin import Tally """Names of tests to be included in Spack's test suite""" test_names = [ - 'architecture', 'versions', 'url_parse', 'url_substitution', 'packages', - 'stage', 'spec_syntax', 'spec_semantics', 'spec_dag', 'concretize', - 'multimethod', 'install', 'package_sanity', 'config', 'directory_layout', - 'pattern', 'python_version', 'git_fetch', 'svn_fetch', 'hg_fetch', - 'mirror', 'modules', 'url_extrapolate', 'cc', 'link_tree', 'spec_yaml', - 'optional_deps', 'make_executable', 'build_system_guess', 'lock', - 'database', 'namespace_trie', 'yaml', 'sbang', 'environment', - 'concretize_preferences', 'cmd.find', 'cmd.uninstall', 'cmd.test_install', - 'cmd.test_compiler_cmd', 'cmd.module' + 'architecture', + 'build_system_guess', + 'cc', + 'cmd.find', + 'cmd.module', + 'cmd.test_compiler_cmd', + 'cmd.test_install', + 'cmd.uninstall', + 'concretize', + 'concretize_preferences', + 'config', + 'configure_guess', + 'database', + 'directory_layout', + 'environment', + 'git_fetch', + 'hg_fetch', + 'install', + 'link_tree', + 'lock', + 'make_executable', + 'mirror', + 'modules', + 'multimethod', + 'namespace_trie', + 'optional_deps', + 'package_sanity', + 'packages', + 'pattern', + 'python_version', + 'sbang', + 'spec_dag', + 'spec_semantics', + 'spec_syntax', + 'spec_yaml', + 'stage', + 'svn_fetch', + 'url_extrapolate', + 'url_parse', + 'url_substitution', + 'versions', + 'virtual', + 'yaml', ] diff --git a/lib/spack/spack/test/virtual.py b/lib/spack/spack/test/virtual.py new file mode 100644 index 0000000000..7699165554 --- /dev/null +++ b/lib/spack/spack/test/virtual.py @@ -0,0 +1,43 @@ +############################################################################## +# Copyright (c) 2013-2016, Lawrence Livermore National Security, LLC. +# Produced at the Lawrence Livermore National Laboratory. +# +# This file is part of Spack. +# Created by Todd Gamblin, tgamblin@llnl.gov, All rights reserved. +# LLNL-CODE-647188 +# +# For details, see https://github.com/llnl/spack +# Please also see the LICENSE file for our notice and the LGPL. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU Lesser General Public License (as +# published by the Free Software Foundation) version 2.1, February 1999. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the IMPLIED WARRANTY OF +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the terms and +# conditions of the GNU Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this program; if not, write to the Free Software +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +############################################################################## +from StringIO import StringIO +import unittest + +import spack +from spack.virtual import ProviderIndex + + +class VirtualTest(unittest.TestCase): + + def test_write_and_read(self): + p = ProviderIndex(spack.repo.all_package_names()) + + ostream = StringIO () + p.to_yaml(ostream) + + istream = StringIO(ostream.getvalue()) + q = ProviderIndex.from_yaml(istream) + + self.assertTrue(p == q) diff --git a/lib/spack/spack/virtual.py b/lib/spack/spack/virtual.py index bb8333f023..bf6d8227a4 100644 --- a/lib/spack/spack/virtual.py +++ b/lib/spack/spack/virtual.py @@ -25,8 +25,12 @@ """ The ``virtual`` module contains utility classes for virtual dependencies. """ -import spack.spec import itertools +import yaml +from yaml.error import MarkedYAMLError + +import spack + class ProviderIndex(object): """This is a dict of dicts used for finding providers of particular @@ -45,10 +49,11 @@ class ProviderIndex(object): Calling providers_for(spec) will find specs that provide a matching implementation of MPI. """ - def __init__(self, specs, **kwargs): + def __init__(self, specs=None, **kwargs): # TODO: come up with another name for this. This "restricts" values to # the verbatim impu specs (i.e., it doesn't pre-apply package's constraints, and # keeps things as broad as possible, so it's really the wrong name) + if specs is None: specs = [] self.restrict = kwargs.setdefault('restrict', False) self.providers = {} @@ -64,7 +69,7 @@ class ProviderIndex(object): def update(self, spec): - if type(spec) != spack.spec.Spec: + if not isinstance(spec, spack.spec.Spec): spec = spack.spec.Spec(spec) if not spec.name: @@ -75,7 +80,8 @@ class ProviderIndex(object): pkg = spec.package for provided_spec, provider_spec in pkg.provided.iteritems(): - provider_spec.compiler_flags = spec.compiler_flags.copy()#We want satisfaction other than flags + # We want satisfaction other than flags + provider_spec.compiler_flags = spec.compiler_flags.copy() if provider_spec.satisfies(spec, deps=False): provided_name = provided_spec.name @@ -164,3 +170,44 @@ class ProviderIndex(object): result[name] = crossed return all(c in result for c in common) + + + def to_yaml(self, stream=None): + provider_list = dict( + (name, [[vpkg.to_node_dict(), [p.to_node_dict() for p in pset]] + for vpkg, pset in pdict.items()]) + for name, pdict in self.providers.items()) + + yaml.dump({'provider_index': {'providers': provider_list}}, + stream=stream) + + + @staticmethod + def from_yaml(stream): + try: + yfile = yaml.load(stream) + except MarkedYAMLError, e: + raise spack.spec.SpackYAMLError( + "error parsing YAML ProviderIndex cache:", str(e)) + + if not isinstance(yfile, dict): + raise spack.spec.SpackYAMLError( + "YAML ProviderIndex was not a dict.") + + if not 'provider_index' in yfile: + raise spack.spec.SpackYAMLError( + "YAML ProviderIndex does not start with 'provider_index'") + + index = ProviderIndex() + providers = yfile['provider_index']['providers'] + index.providers = dict( + (name, dict((spack.spec.Spec.from_node_dict(vpkg), + set(spack.spec.Spec.from_node_dict(p) for p in plist)) + for vpkg, plist in pdict_list)) + for name, pdict_list in providers.items()) + + return index + + + def __eq__(self, other): + return self.providers == other.providers -- cgit v1.2.3-60-g2f50