Save progress. import gov.llnl.spack.mpich works.
This commit is contained in:
parent
a2f2e6a4ff
commit
360b307f68
@ -220,6 +220,13 @@ def colify(elts, **options):
|
|||||||
|
|
||||||
|
|
||||||
def colify_table(table, **options):
|
def colify_table(table, **options):
|
||||||
|
"""Version of colify() for data expressed in rows, (list of lists).
|
||||||
|
|
||||||
|
Same as regular colify but takes a list of lists, where each
|
||||||
|
sub-list must be the same length, and each is interpreted as a
|
||||||
|
row in a table. Regular colify displays a sequential list of
|
||||||
|
values in columns.
|
||||||
|
"""
|
||||||
if table is None:
|
if table is None:
|
||||||
raise TypeError("Can't call colify_table on NoneType")
|
raise TypeError("Can't call colify_table on NoneType")
|
||||||
elif not table or not table[0]:
|
elif not table or not table[0]:
|
||||||
|
@ -23,8 +23,10 @@
|
|||||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
##############################################################################
|
##############################################################################
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import tempfile
|
import tempfile
|
||||||
from llnl.util.filesystem import *
|
from llnl.util.filesystem import *
|
||||||
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
# This lives in $prefix/lib/spack/spack/__file__
|
# This lives in $prefix/lib/spack/spack/__file__
|
||||||
prefix = ancestor(__file__, 4)
|
prefix = ancestor(__file__, 4)
|
||||||
@ -42,6 +44,7 @@
|
|||||||
hooks_path = join_path(module_path, "hooks")
|
hooks_path = join_path(module_path, "hooks")
|
||||||
var_path = join_path(prefix, "var", "spack")
|
var_path = join_path(prefix, "var", "spack")
|
||||||
stage_path = join_path(var_path, "stage")
|
stage_path = join_path(var_path, "stage")
|
||||||
|
packages_path = join_path(var_path, "packages")
|
||||||
opt_path = join_path(prefix, "opt")
|
opt_path = join_path(prefix, "opt")
|
||||||
install_path = join_path(opt_path, "spack")
|
install_path = join_path(opt_path, "spack")
|
||||||
share_path = join_path(prefix, "share", "spack")
|
share_path = join_path(prefix, "share", "spack")
|
||||||
@ -55,9 +58,12 @@
|
|||||||
#
|
#
|
||||||
# Set up the default packages database.
|
# Set up the default packages database.
|
||||||
#
|
#
|
||||||
from spack.packages import PackageDB
|
import spack.packages
|
||||||
packages_path = join_path(var_path, "packages")
|
_repo_paths = spack.config.get_repos_config()
|
||||||
db = PackageDB()
|
if not _repo_paths:
|
||||||
|
tty.die("Spack configuration contains no package repositories.")
|
||||||
|
db = spack.packages.PackageFinder(*_repo_paths)
|
||||||
|
sys.meta_path.append(db)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Paths to mock files for testing.
|
# Paths to mock files for testing.
|
||||||
|
@ -32,7 +32,7 @@
|
|||||||
import spack.spec
|
import spack.spec
|
||||||
import spack.config
|
import spack.config
|
||||||
from spack.util.environment import get_path
|
from spack.util.environment import get_path
|
||||||
from spack.packages import repo_config
|
from spack.packages import repo_config_filename
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import exceptions
|
import exceptions
|
||||||
@ -50,13 +50,8 @@ def setup_parser(subparser):
|
|||||||
create_parser = sp.add_parser('create', help=repo_create.__doc__)
|
create_parser = sp.add_parser('create', help=repo_create.__doc__)
|
||||||
create_parser.add_argument('directory', help="Directory containing the packages.")
|
create_parser.add_argument('directory', help="Directory containing the packages.")
|
||||||
create_parser.add_argument('name', help="Name of new package repository.")
|
create_parser.add_argument('name', help="Name of new package repository.")
|
||||||
<<<<<<< HEAD:lib/spack/spack/cmd/packagerepo.py
|
|
||||||
|
|
||||||
remove_parser = sp.add_parser('remove', help=packagerepo_remove.__doc__)
|
|
||||||
=======
|
|
||||||
|
|
||||||
remove_parser = sp.add_parser('remove', help=repo_remove.__doc__)
|
remove_parser = sp.add_parser('remove', help=repo_remove.__doc__)
|
||||||
>>>>>>> Save changes to external repo integration:lib/spack/spack/cmd/repo.py
|
|
||||||
remove_parser.add_argument('name')
|
remove_parser.add_argument('name')
|
||||||
|
|
||||||
list_parser = sp.add_parser('list', help=repo_list.__doc__)
|
list_parser = sp.add_parser('list', help=repo_list.__doc__)
|
||||||
@ -81,7 +76,7 @@ def repo_add(args):
|
|||||||
"""Add package sources to the Spack configuration."""
|
"""Add package sources to the Spack configuration."""
|
||||||
if not add_to_config(args.directory):
|
if not add_to_config(args.directory):
|
||||||
tty.die('Repo directory %s already exists in the repo list' % dir)
|
tty.die('Repo directory %s already exists in the repo list' % dir)
|
||||||
|
|
||||||
|
|
||||||
def repo_create(args):
|
def repo_create(args):
|
||||||
"""Create a new package repo at a directory and name"""
|
"""Create a new package repo at a directory and name"""
|
||||||
@ -95,13 +90,13 @@ def repo_create(args):
|
|||||||
mkdirp(dir)
|
mkdirp(dir)
|
||||||
except exceptions.OSError, e:
|
except exceptions.OSError, e:
|
||||||
tty.die('Failed to create new directory %s' % dir)
|
tty.die('Failed to create new directory %s' % dir)
|
||||||
path = os.path.join(dir, repo_config)
|
path = os.path.join(dir, repo_config_filename)
|
||||||
try:
|
try:
|
||||||
with closing(open(path, 'w')) as repofile:
|
with closing(open(path, 'w')) as repofile:
|
||||||
repofile.write(name + '\n')
|
repofile.write(name + '\n')
|
||||||
except exceptions.IOError, e:
|
except exceptions.IOError, e:
|
||||||
tty.die('Could not create new file %s' % path)
|
tty.die('Could not create new file %s' % path)
|
||||||
|
|
||||||
if not add_to_config(args.directory):
|
if not add_to_config(args.directory):
|
||||||
tty.warn('Repo directory %s already exists in the repo list' % dir)
|
tty.warn('Repo directory %s already exists in the repo list' % dir)
|
||||||
|
|
||||||
@ -118,8 +113,8 @@ def repo_list(args):
|
|||||||
fmt = "%%-%ds%%s" % (max_len + 4)
|
fmt = "%%-%ds%%s" % (max_len + 4)
|
||||||
for root in root_names:
|
for root in root_names:
|
||||||
print fmt % (root[0], root[1])
|
print fmt % (root[0], root[1])
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def repo(parser, args):
|
def repo(parser, args):
|
||||||
action = { 'add' : repo_add,
|
action = { 'add' : repo_add,
|
||||||
|
@ -269,7 +269,9 @@ def get_repos_config():
|
|||||||
config = get_config()
|
config = get_config()
|
||||||
if 'repos' not in config:
|
if 'repos' not in config:
|
||||||
return []
|
return []
|
||||||
return config['repos']
|
|
||||||
|
repo_list = config['repos']
|
||||||
|
return [substitute_spack_prefix(repo) for repo in repo_list]
|
||||||
|
|
||||||
|
|
||||||
def get_mirror_config():
|
def get_mirror_config():
|
||||||
|
@ -28,7 +28,6 @@
|
|||||||
import inspect
|
import inspect
|
||||||
import glob
|
import glob
|
||||||
import imp
|
import imp
|
||||||
import spack.config
|
|
||||||
import re
|
import re
|
||||||
import itertools
|
import itertools
|
||||||
import traceback
|
import traceback
|
||||||
@ -41,149 +40,327 @@
|
|||||||
import spack.error
|
import spack.error
|
||||||
import spack.spec
|
import spack.spec
|
||||||
from spack.virtual import ProviderIndex
|
from spack.virtual import ProviderIndex
|
||||||
from spack.util.naming import mod_to_class, validate_module_name
|
from spack.util.naming import *
|
||||||
from sets import Set
|
|
||||||
from spack.repo_loader import RepoLoader, imported_packages_module, package_file_name
|
|
||||||
|
|
||||||
# Filename for package repo names
|
# Filename for package repo names
|
||||||
repo_config = 'repo.yaml'
|
repo_config_filename = '_repo.yaml'
|
||||||
|
|
||||||
|
# Filename for packages in repos.
|
||||||
|
package_file_name = 'package.py'
|
||||||
|
|
||||||
def _autospec(function):
|
def _autospec(function):
|
||||||
"""Decorator that automatically converts the argument of a single-arg
|
"""Decorator that automatically converts the argument of a single-arg
|
||||||
function to a Spec."""
|
function to a Spec."""
|
||||||
def converter(self, spec_like, **kwargs):
|
def converter(self, spec_like, *args, **kwargs):
|
||||||
if not isinstance(spec_like, spack.spec.Spec):
|
if not isinstance(spec_like, spack.spec.Spec):
|
||||||
spec_like = spack.spec.Spec(spec_like)
|
spec_like = spack.spec.Spec(spec_like)
|
||||||
return function(self, spec_like, **kwargs)
|
return function(self, spec_like, *args, **kwargs)
|
||||||
return converter
|
return converter
|
||||||
|
|
||||||
|
|
||||||
def sliding_window(seq, n):
|
class NamespaceTrie(object):
|
||||||
it = iter(seq)
|
def __init__(self):
|
||||||
result = tuple(itertools.islice(it, n))
|
self._elements = {}
|
||||||
if len(result) == n:
|
|
||||||
yield result
|
|
||||||
for elem in it:
|
|
||||||
result = result[1:] + (elem,)
|
|
||||||
yield result
|
|
||||||
|
|
||||||
|
|
||||||
class PackageDB(object):
|
def __setitem__(self, namespace, repo):
|
||||||
|
parts = namespace.split('.')
|
||||||
|
cur = self._elements
|
||||||
|
for p in parts[:-1]:
|
||||||
|
if p not in cur:
|
||||||
|
cur[p] = {}
|
||||||
|
cur = cur[p]
|
||||||
|
|
||||||
|
cur[parts[-1]] = repo
|
||||||
|
|
||||||
|
|
||||||
|
def __getitem__(self, namespace):
|
||||||
|
parts = namespace.split('.')
|
||||||
|
cur = self._elements
|
||||||
|
for p in parts:
|
||||||
|
if p not in cur:
|
||||||
|
raise KeyError("Can't find namespace %s in trie" % namespace)
|
||||||
|
cur = cur[p]
|
||||||
|
return cur
|
||||||
|
|
||||||
|
|
||||||
|
def __contains__(self, namespace):
|
||||||
|
parts = namespace.split('.')
|
||||||
|
cur = self._elements
|
||||||
|
for p in parts:
|
||||||
|
if not isinstance(cur, dict):
|
||||||
|
return False
|
||||||
|
if p not in cur:
|
||||||
|
return False
|
||||||
|
cur = cur[p]
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PackageFinder(object):
|
||||||
|
"""A PackageFinder is a wrapper around a list of PackageDBs.
|
||||||
|
|
||||||
|
It functions exactly like a PackageDB, but it operates on the
|
||||||
|
combined results of the PackageDBs in its list instead of on a
|
||||||
|
single package repository.
|
||||||
|
"""
|
||||||
def __init__(self, *repo_dirs):
|
def __init__(self, *repo_dirs):
|
||||||
"""Construct a new package database from a list of directories.
|
|
||||||
|
|
||||||
Args:
|
|
||||||
repo_dirs List of directories containing packages.
|
|
||||||
|
|
||||||
If ``repo_dirs`` is empty, gets repository list from Spack configuration.
|
|
||||||
"""
|
|
||||||
if not repo_dirs:
|
|
||||||
repo_dirs = spack.config.get_repos_config()
|
|
||||||
if not repo_dirs:
|
|
||||||
tty.die("Spack configuration contains no package repositories.")
|
|
||||||
|
|
||||||
# Collect the repos from the config file and read their names
|
|
||||||
# from the file system
|
|
||||||
repo_dirs = [spack.config.substitute_spack_prefix(rd) for rd in repo_dirs]
|
|
||||||
|
|
||||||
self.repos = []
|
self.repos = []
|
||||||
for rdir in repo_dirs:
|
self.by_namespace = NamespaceTrie()
|
||||||
rname = self._read_reponame_from_directory(rdir)
|
self.by_path = {}
|
||||||
if rname:
|
|
||||||
self.repos.append((self._read_reponame_from_directory(rdir), rdir))
|
for root in repo_dirs:
|
||||||
|
repo = PackageDB(root)
|
||||||
|
self.put_last(repo)
|
||||||
|
|
||||||
|
|
||||||
by_path = sorted(self.repos, key=lambda r:r[1])
|
def _check_repo(self, repo):
|
||||||
by_name = sorted(self.repos, key=lambda r:r[0])
|
if repo.root in self.by_path:
|
||||||
|
raise DuplicateRepoError("Package repos are the same",
|
||||||
|
repo, self.by_path[repo.root])
|
||||||
|
|
||||||
for r1, r2 in by_path:
|
if repo.namespace in self.by_namespace:
|
||||||
if r1[1] == r2[1]:
|
tty.error("Package repos cannot have the same name",
|
||||||
tty.die("Package repos are the same:",
|
repo, self.by_namespace[repo.namespace])
|
||||||
" %20s %s" % r1, " %20s %s" % r2)
|
|
||||||
|
|
||||||
for r1, r2 in by_name:
|
|
||||||
if r1[0] == r2[0]:
|
|
||||||
tty.die("Package repos cannot have the same name:",
|
|
||||||
" %20s %s" % r1, " %20s %s" % r2)
|
|
||||||
|
|
||||||
# For each repo, create a RepoLoader
|
|
||||||
self.repo_loaders = dict((name, RepoLoader(name, path))
|
|
||||||
for name, path in self.repos)
|
|
||||||
|
|
||||||
self.instances = {}
|
|
||||||
self.provider_index = None
|
|
||||||
|
|
||||||
|
|
||||||
def _read_reponame_from_directory(self, dir):
|
def _add(self, repo):
|
||||||
"""For a packagerepo directory, read the repo name from the
|
self._check_repo(repo)
|
||||||
$root/repo.yaml file"""
|
self.by_namespace[repo.namespace] = repo
|
||||||
path = os.path.join(dir, repo_config)
|
self.by_path[repo.root] = repo
|
||||||
|
|
||||||
try:
|
|
||||||
with open(path) as reponame_file:
|
|
||||||
yaml_data = yaml.load(reponame_file)
|
|
||||||
|
|
||||||
if (not yaml_data or
|
def put_first(self, repo):
|
||||||
'repo' not in yaml_data or
|
self._add(repo)
|
||||||
'namespace' not in yaml_data['repo']):
|
self.repos.insert(0, repo)
|
||||||
tty.die("Invalid %s in %s" % (repo_config, dir))
|
|
||||||
|
|
||||||
name = yaml_data['repo']['namespace']
|
|
||||||
if not re.match(r'[a-zA-Z][a-zA-Z0-9_.]+', name):
|
def put_last(self, repo):
|
||||||
tty.die(
|
self._add(repo)
|
||||||
"Package repo name '%s', read from %s, is an invalid name. "
|
self.repos.append(repo)
|
||||||
"Repo names must began with a letter and only contain "
|
|
||||||
"letters and numbers." % (name, path))
|
|
||||||
|
def remove(self, repo):
|
||||||
|
if repo in self.repos:
|
||||||
|
self.repos.remove(repo)
|
||||||
|
|
||||||
|
|
||||||
|
def swap(self, other):
|
||||||
|
repos = self.repos
|
||||||
|
by_namespace = self.by_namespace
|
||||||
|
by_path = self.by_path
|
||||||
|
|
||||||
|
self.repos = other.repos
|
||||||
|
self.by_namespace = other.by_namespace
|
||||||
|
self.by_pah = other.by_path
|
||||||
|
|
||||||
|
other.repos = repos
|
||||||
|
other.by_namespace = by_namespace
|
||||||
|
other.by_path = by_path
|
||||||
|
|
||||||
|
|
||||||
|
def all_package_names(self):
|
||||||
|
all_pkgs = set()
|
||||||
|
for repo in self.repos:
|
||||||
|
all_pkgs.update(set(repo.all_package_names()))
|
||||||
|
return all_pkgs
|
||||||
|
|
||||||
|
|
||||||
|
def all_packages(self):
|
||||||
|
for name in self.all_package_names():
|
||||||
|
yield self.get(name)
|
||||||
|
|
||||||
|
|
||||||
|
def providers_for(self, vpkg_name):
|
||||||
|
# TODO: USE MORE THAN FIRST REPO
|
||||||
|
return self.repos[0].providers_for(vpkg_name)
|
||||||
|
|
||||||
|
|
||||||
|
def _get_spack_pkg_name(self, repo, py_module_name):
|
||||||
|
"""Allow users to import Spack packages using legal Python identifiers.
|
||||||
|
|
||||||
|
A python identifier might map to many different Spack package
|
||||||
|
names due to hyphen/underscore ambiguity.
|
||||||
|
|
||||||
|
Easy example:
|
||||||
|
num3proxy -> 3proxy
|
||||||
|
|
||||||
|
Ambiguous:
|
||||||
|
foo_bar -> foo_bar, foo-bar
|
||||||
|
|
||||||
|
More ambiguous:
|
||||||
|
foo_bar_baz -> foo_bar_baz, foo-bar-baz, foo_bar-baz, foo-bar_baz
|
||||||
|
"""
|
||||||
|
if py_module_name in repo:
|
||||||
|
return py_module_name
|
||||||
|
|
||||||
|
options = possible_spack_module_names(py_module_name)
|
||||||
|
options.remove(py_module_name)
|
||||||
|
for name in options:
|
||||||
|
if name in repo:
|
||||||
return name
|
return name
|
||||||
except exceptions.IOError, e:
|
|
||||||
tty.die("Error reading %s when opening %s" % (repo_config, dir))
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def find_module(self, fullname, path=None):
|
||||||
|
if fullname in self.by_namespace:
|
||||||
|
return self
|
||||||
|
|
||||||
|
namespace, dot, module_name = fullname.rpartition('.')
|
||||||
|
if namespace not in self.by_namespace:
|
||||||
|
return None
|
||||||
|
|
||||||
|
repo = self.by_namespace[namespace]
|
||||||
|
name = self._get_spack_pkg_name(repo, module_name)
|
||||||
|
if not name:
|
||||||
|
return None
|
||||||
|
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
def load_module(self, fullname):
|
||||||
|
if fullname in sys.modules:
|
||||||
|
return sys.modules[fullname]
|
||||||
|
|
||||||
|
if fullname in self.by_namespace:
|
||||||
|
ns = self.by_namespace[fullname]
|
||||||
|
module = imp.new_module(fullname)
|
||||||
|
module.__file__ = "<spack-namespace>"
|
||||||
|
module.__path__ = []
|
||||||
|
module.__package__ = fullname
|
||||||
|
|
||||||
|
else:
|
||||||
|
namespace, dot, module_name = fullname.rpartition('.')
|
||||||
|
if namespace not in self.by_namespace:
|
||||||
|
raise ImportError(
|
||||||
|
"No Spack repository with namespace %s" % namespace)
|
||||||
|
|
||||||
|
repo = self.by_namespace[namespace]
|
||||||
|
name = self._get_spack_pkg_name(repo, module_name)
|
||||||
|
if not name:
|
||||||
|
raise ImportError(
|
||||||
|
"No module %s in Spack repository %s" % (module_name, repo))
|
||||||
|
|
||||||
|
fullname = namespace + '.' + name
|
||||||
|
file_path = os.path.join(repo.root, name, package_file_name)
|
||||||
|
module = imp.load_source(fullname, file_path)
|
||||||
|
module.__package__ = namespace
|
||||||
|
|
||||||
|
module.__loader__ = self
|
||||||
|
sys.modules[fullname] = module
|
||||||
|
return module
|
||||||
|
|
||||||
|
|
||||||
@_autospec
|
@_autospec
|
||||||
def get(self, spec, **kwargs):
|
def get(self, spec, new=False):
|
||||||
|
for repo in self.repos:
|
||||||
|
if spec.name in repo:
|
||||||
|
return repo.get(spec, new)
|
||||||
|
raise UnknownPackageError(spec.name)
|
||||||
|
|
||||||
|
|
||||||
|
def get_repo(self, namespace):
|
||||||
|
if namespace in self.by_namespace:
|
||||||
|
repo = self.by_namespace[namespace]
|
||||||
|
if isinstance(repo, PackageDB):
|
||||||
|
return repo
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def exists(self, pkg_name):
|
||||||
|
return any(repo.exists(pkg_name) for repo in self.repos)
|
||||||
|
|
||||||
|
|
||||||
|
def __contains__(self, pkg_name):
|
||||||
|
return self.exists(pkg_name)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PackageDB(object):
|
||||||
|
"""Class representing a package repository in the filesystem.
|
||||||
|
|
||||||
|
Each package repository must have a top-level configuration file
|
||||||
|
called `_repo.yaml`.
|
||||||
|
|
||||||
|
Currently, `_repo.yaml` this must define:
|
||||||
|
|
||||||
|
`namespace`:
|
||||||
|
A Python namespace where the repository's packages should live.
|
||||||
|
|
||||||
|
"""
|
||||||
|
def __init__(self, root):
|
||||||
|
"""Instantiate a package repository from a filesystem path."""
|
||||||
|
# Root directory, containing _repo.yaml and package dirs
|
||||||
|
self.root = root
|
||||||
|
|
||||||
|
# Config file in <self.root>/_repo.yaml
|
||||||
|
self.config_file = os.path.join(self.root, repo_config_filename)
|
||||||
|
|
||||||
|
# Read configuration from _repo.yaml
|
||||||
|
config = self._read_config()
|
||||||
|
if not 'namespace' in config:
|
||||||
|
tty.die('Package repo in %s must define a namespace in %s.'
|
||||||
|
% (self.root, repo_config_filename))
|
||||||
|
|
||||||
|
# Check namespace in the repository configuration.
|
||||||
|
self.namespace = config['namespace']
|
||||||
|
if not re.match(r'[a-zA-Z][a-zA-Z0-9_.]+', self.namespace):
|
||||||
|
tty.die(("Invalid namespace '%s' in '%s'. Namespaces must be "
|
||||||
|
"valid python identifiers separated by '.'")
|
||||||
|
% (self.namespace, self.root))
|
||||||
|
|
||||||
|
# These are internal cache variables.
|
||||||
|
self._instances = {}
|
||||||
|
self._provider_index = None
|
||||||
|
|
||||||
|
|
||||||
|
def _read_config(self):
|
||||||
|
"""Check for a YAML config file in this db's root directory."""
|
||||||
|
try:
|
||||||
|
with open(self.config_file) as reponame_file:
|
||||||
|
yaml_data = yaml.load(reponame_file)
|
||||||
|
|
||||||
|
if (not yaml_data or 'repo' not in yaml_data or
|
||||||
|
not isinstance(yaml_data['repo'], dict)):
|
||||||
|
tty.die("Invalid %s in repository %s"
|
||||||
|
% (repo_config_filename, self.root))
|
||||||
|
|
||||||
|
return yaml_data['repo']
|
||||||
|
|
||||||
|
except exceptions.IOError, e:
|
||||||
|
tty.die("Error reading %s when opening %s"
|
||||||
|
% (self.config_file, self.root))
|
||||||
|
|
||||||
|
|
||||||
|
@_autospec
|
||||||
|
def get(self, spec, new=False):
|
||||||
if spec.virtual:
|
if spec.virtual:
|
||||||
raise UnknownPackageError(spec.name)
|
raise UnknownPackageError(spec.name)
|
||||||
|
|
||||||
if kwargs.get('new', False):
|
if new:
|
||||||
if spec in self.instances:
|
if spec in self._instances:
|
||||||
del self.instances[spec]
|
del self._instances[spec]
|
||||||
|
|
||||||
if not spec in self.instances:
|
if not spec in self._instances:
|
||||||
package_class = self.get_class_for_package_name(spec.name, spec.repo)
|
package_class = self.get_class_for_package_name(spec.name, spec.repo)
|
||||||
try:
|
try:
|
||||||
copy = spec.copy()
|
copy = spec.copy()
|
||||||
self.instances[copy] = package_class(copy)
|
self._instances[copy] = package_class(copy)
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
if spack.debug:
|
if spack.debug:
|
||||||
sys.excepthook(*sys.exc_info())
|
sys.excepthook(*sys.exc_info())
|
||||||
raise FailedConstructorError(spec.name, *sys.exc_info())
|
raise FailedConstructorError(spec.name, *sys.exc_info())
|
||||||
|
|
||||||
return self.instances[spec]
|
return self._instances[spec]
|
||||||
|
|
||||||
|
|
||||||
@_autospec
|
|
||||||
def delete(self, spec):
|
|
||||||
"""Force a package to be recreated."""
|
|
||||||
del self.instances[spec]
|
|
||||||
|
|
||||||
|
|
||||||
def purge(self):
|
|
||||||
"""Clear entire package instance cache."""
|
|
||||||
self.instances.clear()
|
|
||||||
|
|
||||||
|
|
||||||
@_autospec
|
|
||||||
def get_installed(self, spec):
|
|
||||||
"""Get all the installed specs that satisfy the provided spec constraint."""
|
|
||||||
return [s for s in self.installed_package_specs() if s.satisfies(spec)]
|
|
||||||
|
|
||||||
|
|
||||||
@_autospec
|
@_autospec
|
||||||
def providers_for(self, vpkg_spec):
|
def providers_for(self, vpkg_spec):
|
||||||
if self.provider_index is None:
|
if self._provider_index is None:
|
||||||
self.provider_index = ProviderIndex(self.all_package_names())
|
self._provider_index = ProviderIndex(self.all_package_names())
|
||||||
|
|
||||||
providers = self.provider_index.providers_for(vpkg_spec)
|
providers = self._provider_index.providers_for(vpkg_spec)
|
||||||
if not providers:
|
if not providers:
|
||||||
raise UnknownPackageError(vpkg_spec.name)
|
raise UnknownPackageError(vpkg_spec.name)
|
||||||
return providers
|
return providers
|
||||||
@ -194,6 +371,97 @@ def extensions_for(self, extendee_spec):
|
|||||||
return [p for p in self.all_packages() if p.extends(extendee_spec)]
|
return [p for p in self.all_packages() if p.extends(extendee_spec)]
|
||||||
|
|
||||||
|
|
||||||
|
def dirname_for_package_name(self, pkg_name):
|
||||||
|
"""Get the directory name for a particular package. This is the
|
||||||
|
directory that contains its package.py file."""
|
||||||
|
return join_path(self.root, pkg_name)
|
||||||
|
|
||||||
|
|
||||||
|
def filename_for_package_name(self, pkg_name):
|
||||||
|
"""Get the filename for the module we should load for a particular
|
||||||
|
package. Packages for a pacakge DB live in
|
||||||
|
``$root/<package_name>/package.py``
|
||||||
|
|
||||||
|
This will return a proper package.py path even if the
|
||||||
|
package doesn't exist yet, so callers will need to ensure
|
||||||
|
the package exists before importing.
|
||||||
|
"""
|
||||||
|
validate_module_name(pkg_name)
|
||||||
|
pkg_dir = self.dirname_for_package_name(pkg_name)
|
||||||
|
return join_path(pkg_dir, package_file_name)
|
||||||
|
|
||||||
|
|
||||||
|
@memoized
|
||||||
|
def all_package_names(self):
|
||||||
|
"""Generator function for all packages. This looks for
|
||||||
|
``<pkg_name>/package.py`` files within the repo direcotories"""
|
||||||
|
all_package_names = []
|
||||||
|
|
||||||
|
for pkg_name in os.listdir(self.root):
|
||||||
|
pkg_dir = join_path(self.root, pkg_name)
|
||||||
|
pkg_file = join_path(pkg_dir, package_file_name)
|
||||||
|
if os.path.isfile(pkg_file):
|
||||||
|
all_package_names.append(pkg_name)
|
||||||
|
|
||||||
|
return sorted(all_package_names)
|
||||||
|
|
||||||
|
|
||||||
|
def all_packages(self):
|
||||||
|
for name in self.all_package_names():
|
||||||
|
yield self.get(name)
|
||||||
|
|
||||||
|
|
||||||
|
@memoized
|
||||||
|
def exists(self, pkg_name):
|
||||||
|
"""Whether a package with the supplied name exists."""
|
||||||
|
return os.path.exists(self.filename_for_package_name(pkg_name))
|
||||||
|
|
||||||
|
|
||||||
|
@memoized
|
||||||
|
def get_class_for_package_name(self, pkg_name, reponame = None):
|
||||||
|
"""Get an instance of the class for a particular package."""
|
||||||
|
file_path = self.filename_for_package_name(pkg_name)
|
||||||
|
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
if not os.path.isfile(file_path):
|
||||||
|
tty.die("Something's wrong. '%s' is not a file!" % file_path)
|
||||||
|
if not os.access(file_path, os.R_OK):
|
||||||
|
tty.die("Cannot read '%s'!" % file_path)
|
||||||
|
else:
|
||||||
|
raise UnknownPackageError(pkg_name, self.namespace)
|
||||||
|
|
||||||
|
class_name = mod_to_class(pkg_name)
|
||||||
|
module = __import__(self.namespace + '.' + pkg_name, fromlist=[class_name])
|
||||||
|
cls = getattr(module, class_name)
|
||||||
|
if not inspect.isclass(cls):
|
||||||
|
tty.die("%s.%s is not a class" % (pkg_name, class_name))
|
||||||
|
|
||||||
|
return cls
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "<PackageDB '%s' from '%s'>" % (self.namespace, self.root)
|
||||||
|
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
return self.__str__()
|
||||||
|
|
||||||
|
|
||||||
|
def __contains__(self, pkg_name):
|
||||||
|
return self.exists(pkg_name)
|
||||||
|
|
||||||
|
|
||||||
|
#
|
||||||
|
# Below functions deal with installed packages, and should be
|
||||||
|
# moved to some other part of Spack (conbine with
|
||||||
|
# directory_layout?)
|
||||||
|
#
|
||||||
|
@_autospec
|
||||||
|
def get_installed(self, spec):
|
||||||
|
"""Get all the installed specs that satisfy the provided spec constraint."""
|
||||||
|
return [s for s in self.installed_package_specs() if s.satisfies(spec)]
|
||||||
|
|
||||||
|
|
||||||
@_autospec
|
@_autospec
|
||||||
def installed_extensions_for(self, extendee_spec):
|
def installed_extensions_for(self, extendee_spec):
|
||||||
for s in self.installed_package_specs():
|
for s in self.installed_package_specs():
|
||||||
@ -203,53 +471,6 @@ def installed_extensions_for(self, extendee_spec):
|
|||||||
except UnknownPackageError, e:
|
except UnknownPackageError, e:
|
||||||
# Skip packages we know nothing about
|
# Skip packages we know nothing about
|
||||||
continue
|
continue
|
||||||
# TODO: add some conditional way to do this instead of
|
|
||||||
# catching exceptions.
|
|
||||||
|
|
||||||
|
|
||||||
def repo_for_package_name(self, pkg_name, packagerepo_name=None):
|
|
||||||
"""Find the dirname for a package and the packagerepo it came from
|
|
||||||
if packagerepo_name is not None, then search for the package in the
|
|
||||||
specified packagerepo"""
|
|
||||||
#Look for an existing package under any matching packagerepos
|
|
||||||
roots = [pkgrepo for pkgrepo in self.repos
|
|
||||||
if not packagerepo_name or packagerepo_name == pkgrepo[0]]
|
|
||||||
|
|
||||||
if not roots:
|
|
||||||
tty.die("Package repo %s does not exist" % packagerepo_name)
|
|
||||||
|
|
||||||
for pkgrepo in roots:
|
|
||||||
path = join_path(pkgrepo[1], pkg_name)
|
|
||||||
if os.path.exists(path):
|
|
||||||
return (pkgrepo[0], path)
|
|
||||||
|
|
||||||
repo_to_add_to = roots[-1]
|
|
||||||
return (repo_to_add_to[0], join_path(repo_to_add_to[1], pkg_name))
|
|
||||||
|
|
||||||
|
|
||||||
def dirname_for_package_name(self, pkg_name, packagerepo_name=None):
|
|
||||||
"""Get the directory name for a particular package. This is the
|
|
||||||
directory that contains its package.py file."""
|
|
||||||
return self.repo_for_package_name(pkg_name, packagerepo_name)[1]
|
|
||||||
|
|
||||||
|
|
||||||
def filename_for_package_name(self, pkg_name, packagerepo_name=None):
|
|
||||||
"""Get the filename for the module we should load for a particular
|
|
||||||
package. Packages for a pacakge DB live in
|
|
||||||
``$root/<package_name>/package.py``
|
|
||||||
|
|
||||||
This will return a proper package.py path even if the
|
|
||||||
package doesn't exist yet, so callers will need to ensure
|
|
||||||
the package exists before importing.
|
|
||||||
|
|
||||||
If a packagerepo is specified, then return existing
|
|
||||||
or new paths in the specified packagerepo directory. If no
|
|
||||||
package repo is supplied, return an existing path from any
|
|
||||||
package repo, and new paths in the default package repo.
|
|
||||||
"""
|
|
||||||
validate_module_name(pkg_name)
|
|
||||||
pkg_dir = self.dirname_for_package_name(pkg_name, packagerepo_name)
|
|
||||||
return join_path(pkg_dir, package_file_name)
|
|
||||||
|
|
||||||
|
|
||||||
def installed_package_specs(self):
|
def installed_package_specs(self):
|
||||||
@ -275,52 +496,6 @@ def installed_known_package_specs(self):
|
|||||||
yield spec
|
yield spec
|
||||||
|
|
||||||
|
|
||||||
@memoized
|
|
||||||
def all_package_names(self):
|
|
||||||
"""Generator function for all packages. This looks for
|
|
||||||
``<pkg_name>/package.py`` files within the repo direcotories"""
|
|
||||||
all_packages = Set()
|
|
||||||
for repo in self.repos:
|
|
||||||
dir = repo[1]
|
|
||||||
if not os.path.isdir(dir):
|
|
||||||
continue
|
|
||||||
for pkg_name in os.listdir(dir):
|
|
||||||
pkg_dir = join_path(dir, pkg_name)
|
|
||||||
pkg_file = join_path(pkg_dir, package_file_name)
|
|
||||||
if os.path.isfile(pkg_file):
|
|
||||||
all_packages.add(pkg_name)
|
|
||||||
all_package_names = list(all_packages)
|
|
||||||
all_package_names.sort()
|
|
||||||
return all_package_names
|
|
||||||
|
|
||||||
|
|
||||||
def all_packages(self):
|
|
||||||
for name in self.all_package_names():
|
|
||||||
yield self.get(name)
|
|
||||||
|
|
||||||
|
|
||||||
@memoized
|
|
||||||
def exists(self, pkg_name):
|
|
||||||
"""Whether a package with the supplied name exists ."""
|
|
||||||
return os.path.exists(self.filename_for_package_name(pkg_name))
|
|
||||||
|
|
||||||
|
|
||||||
@memoized
|
|
||||||
def get_class_for_package_name(self, pkg_name, reponame = None):
|
|
||||||
"""Get an instance of the class for a particular package."""
|
|
||||||
(reponame, repodir) = self.repo_for_package_name(pkg_name, reponame)
|
|
||||||
module_name = imported_packages_module + '.' + reponame + '.' + pkg_name
|
|
||||||
|
|
||||||
module = self.repo_loaders[reponame].get_module(pkg_name)
|
|
||||||
|
|
||||||
class_name = mod_to_class(pkg_name)
|
|
||||||
cls = getattr(module, class_name)
|
|
||||||
if not inspect.isclass(cls):
|
|
||||||
tty.die("%s.%s is not a class" % (pkg_name, class_name))
|
|
||||||
|
|
||||||
return cls
|
|
||||||
|
|
||||||
|
|
||||||
class UnknownPackageError(spack.error.SpackError):
|
class UnknownPackageError(spack.error.SpackError):
|
||||||
"""Raised when we encounter a package spack doesn't have."""
|
"""Raised when we encounter a package spack doesn't have."""
|
||||||
def __init__(self, name, repo=None):
|
def __init__(self, name, repo=None):
|
||||||
@ -333,6 +508,13 @@ def __init__(self, name, repo=None):
|
|||||||
self.name = name
|
self.name = name
|
||||||
|
|
||||||
|
|
||||||
|
class DuplicateRepoError(spack.error.SpackError):
|
||||||
|
"""Raised when duplicate repos are added to a PackageFinder."""
|
||||||
|
def __init__(self, msg, repo1, repo2):
|
||||||
|
super(UnknownPackageError, self).__init__(
|
||||||
|
"%s: %s, %s" % (msg, repo1, repo2))
|
||||||
|
|
||||||
|
|
||||||
class FailedConstructorError(spack.error.SpackError):
|
class FailedConstructorError(spack.error.SpackError):
|
||||||
"""Raised when a package's class constructor fails."""
|
"""Raised when a package's class constructor fails."""
|
||||||
def __init__(self, name, exc_type, exc_obj, exc_tb):
|
def __init__(self, name, exc_type, exc_obj, exc_tb):
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
# Name of the package file inside a package directory
|
# Name of the package file inside a package directory
|
||||||
package_file_name = 'package.py'
|
package_file_name = 'package.py'
|
||||||
|
|
||||||
import sys
|
|
||||||
class LazyLoader:
|
class LazyLoader:
|
||||||
"""The LazyLoader handles cases when repo modules or classes
|
"""The LazyLoader handles cases when repo modules or classes
|
||||||
are imported. It watches for 'spack.repos.*' loads, then
|
are imported. It watches for 'spack.repos.*' loads, then
|
||||||
@ -21,15 +20,6 @@ def find_module(self, fullname, pathname):
|
|||||||
if not fullname.startswith(imported_packages_module):
|
if not fullname.startswith(imported_packages_module):
|
||||||
return None
|
return None
|
||||||
|
|
||||||
print "HERE ==="
|
|
||||||
print
|
|
||||||
for line in traceback.format_stack():
|
|
||||||
print " ", line.strip()
|
|
||||||
print
|
|
||||||
print "full: ", fullname
|
|
||||||
print "path: ", pathname
|
|
||||||
print
|
|
||||||
|
|
||||||
partial_name = fullname[len(imported_packages_module)+1:]
|
partial_name = fullname[len(imported_packages_module)+1:]
|
||||||
|
|
||||||
print "partial: ", partial_name
|
print "partial: ", partial_name
|
||||||
@ -50,7 +40,7 @@ def find_module(self, fullname, pathname):
|
|||||||
def load_module(self, fullname):
|
def load_module(self, fullname):
|
||||||
return self.mod
|
return self.mod
|
||||||
|
|
||||||
sys.meta_path.append(LazyLoader())
|
#sys.meta_path.append(LazyLoader())
|
||||||
|
|
||||||
_reponames = {}
|
_reponames = {}
|
||||||
class RepoNamespace(types.ModuleType):
|
class RepoNamespace(types.ModuleType):
|
||||||
@ -59,7 +49,6 @@ class RepoNamespace(types.ModuleType):
|
|||||||
this class will use __getattr__ to translate the 'original'
|
this class will use __getattr__ to translate the 'original'
|
||||||
into one of spack's known repositories"""
|
into one of spack's known repositories"""
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
import sys
|
|
||||||
sys.modules[imported_packages_module] = self
|
sys.modules[imported_packages_module] = self
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
@ -89,7 +78,6 @@ def __init__(self, reponame, repopath):
|
|||||||
if not reponame in _reponames:
|
if not reponame in _reponames:
|
||||||
_reponames[reponame] = self
|
_reponames[reponame] = self
|
||||||
|
|
||||||
import sys
|
|
||||||
sys.modules[self.module_name] = self
|
sys.modules[self.module_name] = self
|
||||||
|
|
||||||
|
|
||||||
@ -110,14 +98,6 @@ def get_module(self, pkg_name):
|
|||||||
import imp
|
import imp
|
||||||
import llnl.util.tty as tty
|
import llnl.util.tty as tty
|
||||||
|
|
||||||
file_path = os.path.join(self.path, pkg_name, package_file_name)
|
|
||||||
if os.path.exists(file_path):
|
|
||||||
if not os.path.isfile(file_path):
|
|
||||||
tty.die("Something's wrong. '%s' is not a file!" % file_path)
|
|
||||||
if not os.access(file_path, os.R_OK):
|
|
||||||
tty.die("Cannot read '%s'!" % file_path)
|
|
||||||
else:
|
|
||||||
raise spack.packages.UnknownPackageError(pkg_name, self.reponame if self.reponame != 'original' else None)
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
module_name = imported_packages_module + '.' + self.reponame + '.' + pkg_name
|
module_name = imported_packages_module + '.' + self.reponame + '.' + pkg_name
|
||||||
|
@ -1714,7 +1714,7 @@ def spec(self):
|
|||||||
spec_repo = lst[-2]
|
spec_repo = lst[-2]
|
||||||
else:
|
else:
|
||||||
spec_name = self.token.value
|
spec_name = self.token.value
|
||||||
(spec_repo, repodir) = spack.db.repo_for_package_name(spec_name)
|
spec_repo = 'gov.llnl.spack'
|
||||||
|
|
||||||
self.check_identifier(spec_name)
|
self.check_identifier(spec_name)
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@
|
|||||||
|
|
||||||
import spack
|
import spack
|
||||||
from spack.spec import Spec
|
from spack.spec import Spec
|
||||||
from spack.packages import PackageDB
|
from spack.packages import PackageFinder
|
||||||
from spack.directory_layout import YamlDirectoryLayout
|
from spack.directory_layout import YamlDirectoryLayout
|
||||||
|
|
||||||
# number of packages to test (to reduce test time)
|
# number of packages to test (to reduce test time)
|
||||||
@ -123,7 +123,7 @@ def test_handle_unknown_package(self):
|
|||||||
information about installed packages' specs to uninstall
|
information about installed packages' specs to uninstall
|
||||||
or query them again if the package goes away.
|
or query them again if the package goes away.
|
||||||
"""
|
"""
|
||||||
mock_db = PackageDB(spack.mock_packages_path)
|
mock_db = PackageFinder(spack.mock_packages_path)
|
||||||
|
|
||||||
not_in_mock = set.difference(
|
not_in_mock = set.difference(
|
||||||
set(spack.db.all_package_names()),
|
set(spack.db.all_package_names()),
|
||||||
@ -145,8 +145,7 @@ def test_handle_unknown_package(self):
|
|||||||
self.layout.create_install_directory(spec)
|
self.layout.create_install_directory(spec)
|
||||||
installed_specs[spec] = self.layout.path_for_spec(spec)
|
installed_specs[spec] = self.layout.path_for_spec(spec)
|
||||||
|
|
||||||
tmp = spack.db
|
spack.db.swap(mock_db)
|
||||||
spack.db = mock_db
|
|
||||||
|
|
||||||
# Now check that even without the package files, we know
|
# Now check that even without the package files, we know
|
||||||
# enough to read a spec from the spec file.
|
# enough to read a spec from the spec file.
|
||||||
@ -161,7 +160,7 @@ def test_handle_unknown_package(self):
|
|||||||
self.assertTrue(spec.eq_dag(spec_from_file))
|
self.assertTrue(spec.eq_dag(spec_from_file))
|
||||||
self.assertEqual(spec.dag_hash(), spec_from_file.dag_hash())
|
self.assertEqual(spec.dag_hash(), spec_from_file.dag_hash())
|
||||||
|
|
||||||
spack.db = tmp
|
spack.db.swap(mock_db)
|
||||||
|
|
||||||
|
|
||||||
def test_find(self):
|
def test_find(self):
|
||||||
|
@ -22,11 +22,12 @@
|
|||||||
# along with this program; if not, write to the Free Software Foundation,
|
# along with this program; if not, write to the Free Software Foundation,
|
||||||
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
# Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
import sys
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import spack
|
import spack
|
||||||
import spack.config
|
import spack.config
|
||||||
from spack.packages import PackageDB
|
from spack.packages import PackageFinder
|
||||||
from spack.spec import Spec
|
from spack.spec import Spec
|
||||||
|
|
||||||
|
|
||||||
@ -43,8 +44,8 @@ def initmock(self):
|
|||||||
# Use the mock packages database for these tests. This allows
|
# Use the mock packages database for these tests. This allows
|
||||||
# us to set up contrived packages that don't interfere with
|
# us to set up contrived packages that don't interfere with
|
||||||
# real ones.
|
# real ones.
|
||||||
self.real_db = spack.db
|
self.db = PackageFinder(spack.mock_packages_path)
|
||||||
spack.db = PackageDB(spack.mock_packages_path)
|
spack.db.swap(self.db)
|
||||||
|
|
||||||
spack.config.clear_config_caches()
|
spack.config.clear_config_caches()
|
||||||
self.real_scopes = spack.config.config_scopes
|
self.real_scopes = spack.config.config_scopes
|
||||||
@ -55,7 +56,8 @@ def initmock(self):
|
|||||||
|
|
||||||
def cleanmock(self):
|
def cleanmock(self):
|
||||||
"""Restore the real packages path after any test."""
|
"""Restore the real packages path after any test."""
|
||||||
spack.db = self.real_db
|
spack.db.swap(self.db)
|
||||||
|
|
||||||
spack.config.config_scopes = self.real_scopes
|
spack.config.config_scopes = self.real_scopes
|
||||||
spack.config.clear_config_caches()
|
spack.config.clear_config_caches()
|
||||||
|
|
||||||
@ -66,5 +68,3 @@ def setUp(self):
|
|||||||
|
|
||||||
def tearDown(self):
|
def tearDown(self):
|
||||||
self.cleanmock()
|
self.cleanmock()
|
||||||
|
|
||||||
|
|
||||||
|
@ -47,10 +47,10 @@ def test_get_all_packages(self):
|
|||||||
|
|
||||||
def test_get_all_mock_packages(self):
|
def test_get_all_mock_packages(self):
|
||||||
"""Get the mock packages once each too."""
|
"""Get the mock packages once each too."""
|
||||||
tmp = spack.db
|
db = PackageFinder(spack.mock_packages_path)
|
||||||
spack.db = PackageDB(spack.mock_packages_path)
|
spack.db.swap(db)
|
||||||
self.check_db()
|
self.check_db()
|
||||||
spack.db = tmp
|
spack.db.swap(db)
|
||||||
|
|
||||||
|
|
||||||
def test_url_versions(self):
|
def test_url_versions(self):
|
||||||
|
@ -44,7 +44,8 @@ def test_package_name(self):
|
|||||||
|
|
||||||
|
|
||||||
def test_package_filename(self):
|
def test_package_filename(self):
|
||||||
filename = spack.db.filename_for_package_name('mpich')
|
repo = spack.db.get_repo('gov.llnl.spack.mock')
|
||||||
|
filename = repo.filename_for_package_name('mpich')
|
||||||
self.assertEqual(filename, join_path(spack.mock_packages_path, 'mpich', 'package.py'))
|
self.assertEqual(filename, join_path(spack.mock_packages_path, 'mpich', 'package.py'))
|
||||||
|
|
||||||
|
|
||||||
@ -54,7 +55,8 @@ def test_package_name(self):
|
|||||||
|
|
||||||
|
|
||||||
def test_nonexisting_package_filename(self):
|
def test_nonexisting_package_filename(self):
|
||||||
filename = spack.db.filename_for_package_name('some-nonexisting-package')
|
repo = spack.db.get_repo('gov.llnl.spack.mock')
|
||||||
|
filename = repo.filename_for_package_name('some-nonexisting-package')
|
||||||
self.assertEqual(filename, join_path(spack.mock_packages_path, 'some-nonexisting-package', 'package.py'))
|
self.assertEqual(filename, join_path(spack.mock_packages_path, 'some-nonexisting-package', 'package.py'))
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
# Need this because of spack.util.string
|
# Need this because of spack.util.string
|
||||||
from __future__ import absolute_import
|
from __future__ import absolute_import
|
||||||
import string
|
import string
|
||||||
|
import itertools
|
||||||
import re
|
import re
|
||||||
|
|
||||||
import spack
|
import spack
|
||||||
|
|
||||||
|
__all__ = ['mod_to_class', 'spack_module_to_python_module', 'valid_module_name',
|
||||||
|
'validate_module_name', 'possible_spack_module_names']
|
||||||
|
|
||||||
# Valid module names can contain '-' but can't start with it.
|
# Valid module names can contain '-' but can't start with it.
|
||||||
_valid_module_re = r'^\w[\w-]*$'
|
_valid_module_re = r'^\w[\w-]*$'
|
||||||
|
|
||||||
@ -42,6 +46,33 @@ def mod_to_class(mod_name):
|
|||||||
return class_name
|
return class_name
|
||||||
|
|
||||||
|
|
||||||
|
def spack_module_to_python_module(mod_name):
|
||||||
|
"""Given a Spack module name, returns the name by which it can be
|
||||||
|
imported in Python.
|
||||||
|
"""
|
||||||
|
if re.match(r'[0-9]', mod_name):
|
||||||
|
mod_name = 'num' + mod_name
|
||||||
|
|
||||||
|
return mod_name.replace('-', '_')
|
||||||
|
|
||||||
|
|
||||||
|
def possible_spack_module_names(python_mod_name):
|
||||||
|
"""Given a Python module name, return a list of all possible spack module
|
||||||
|
names that could correspond to it."""
|
||||||
|
mod_name = re.sub(r'^num(\d)', r'\1', python_mod_name)
|
||||||
|
|
||||||
|
parts = re.split(r'(_)', mod_name)
|
||||||
|
options = [['_', '-']] * mod_name.count('_')
|
||||||
|
|
||||||
|
results = []
|
||||||
|
for subs in itertools.product(*options):
|
||||||
|
s = list(parts)
|
||||||
|
s[1::2] = subs
|
||||||
|
results.append(''.join(s))
|
||||||
|
|
||||||
|
return results
|
||||||
|
|
||||||
|
|
||||||
def valid_module_name(mod_name):
|
def valid_module_name(mod_name):
|
||||||
"""Return whether the mod_name is valid for use in Spack."""
|
"""Return whether the mod_name is valid for use in Spack."""
|
||||||
return bool(re.match(_valid_module_re, mod_name))
|
return bool(re.match(_valid_module_re, mod_name))
|
||||||
|
2
var/spack/mock_packages/_repo.yaml
Normal file
2
var/spack/mock_packages/_repo.yaml
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
repo:
|
||||||
|
namespace: gov.llnl.spack.mock
|
@ -1,2 +0,0 @@
|
|||||||
repo:
|
|
||||||
namespace: mock
|
|
Loading…
Reference in New Issue
Block a user