def view(parser, args): 'Produce a view of a set of packages.' specs = spack.cmd.parse_specs(args.specs) path = args.path[0] view = YamlFilesystemView( path, spack.store.layout, ignore_conflicts=getattr(args, "ignore_conflicts", False), link=os.link if args.action in ["hardlink", "hard"] else os.symlink, verbose=args.verbose) # Process common args and specs if getattr(args, "all", False): specs = view.get_all_specs() if len(specs) == 0: tty.warn("Found no specs in %s" % path) elif args.action in actions_link: # only link commands need to disambiguate specs specs = [spack.cmd.disambiguate_spec(s) for s in specs] elif args.action in actions_status: # no specs implies all if len(specs) == 0: specs = view.get_all_specs() else: specs = relaxed_disambiguate(specs, view) else: # status and remove can map the name to packages in view specs = relaxed_disambiguate(specs, view) with_dependencies = args.dependencies.lower() in ['true', 'yes'] # Map action to corresponding functionality if args.action in actions_link: try: view.add_specs(*specs, with_dependencies=with_dependencies, exclude=args.exclude) except MergeConflictError: tty.info("Some file blocked the merge, adding the '-i' flag will " "ignore this conflict. For more information see e.g. " "https://github.com/spack/spack/issues/9029") raise elif args.action in actions_remove: view.remove_specs(*specs, with_dependencies=with_dependencies, exclude=args.exclude, with_dependents=not args.no_remove_dependents) elif args.action in actions_status: view.print_status(*specs, with_dependencies=with_dependencies) else: tty.error('Unknown action: "%s"' % args.action)
def view(parser, args): 'Produce a view of a set of packages.' path = args.path[0] view = YamlFilesystemView( path, spack.store.layout, ignore_conflicts=getattr(args, "ignore_conflicts", False), link=os.link if args.action in ["hardlink", "hard"] else os.symlink, verbose=args.verbose) # Process common args and specs if getattr(args, "all", False): specs = view.get_all_specs() if len(specs) == 0: tty.warn("Found no specs in %s" % path) elif args.action in actions_link: # only link commands need to disambiguate specs specs = [spack.cmd.disambiguate_spec(s) for s in args.specs] elif args.action in actions_status: # no specs implies all if len(args.specs) == 0: specs = view.get_all_specs() else: specs = relaxed_disambiguate(args.specs, view) else: # status and remove can map the name to packages in view specs = relaxed_disambiguate(args.specs, view) with_dependencies = args.dependencies.lower() in ['true', 'yes'] # Map action to corresponding functionality if args.action in actions_link: view.add_specs(*specs, with_dependencies=with_dependencies, exclude=args.exclude) elif args.action in actions_remove: view.remove_specs(*specs, with_dependencies=with_dependencies, exclude=args.exclude, with_dependents=not args.no_remove_dependents) elif args.action in actions_status: view.print_status(*specs, with_dependencies=with_dependencies) else: tty.error('Unknown action: "%s"' % args.action)
def test_python_namespace_conflict(tmpdir, namespace_extensions, monkeypatch, builtin_and_mock_packages): """Test the view update logic in PythonPackage reports an error when two python extensions with different namespaces have a conflicting __init__ file. """ ext1_prefix, ext2_prefix, py_namespace = namespace_extensions other_namespace = py_namespace + 'other' python_spec = spack.spec.Spec('[email protected]') python_spec._concrete = True ext1_pkg = create_python_ext_pkg('py-extension1', ext1_prefix, python_spec, monkeypatch, py_namespace) ext2_pkg = create_python_ext_pkg('py-extension2', ext2_prefix, python_spec, monkeypatch, other_namespace) view_dir = str(tmpdir.join('view')) layout = DirectoryLayout(view_dir) view = YamlFilesystemView(view_dir, layout) python_pkg = python_spec.package python_pkg.activate(ext1_pkg, view) view.extensions_layout.add_extension(python_spec, ext1_pkg.spec) with pytest.raises(MergeConflictError): python_pkg.activate(ext2_pkg, view)
def test_python_ignore_namespace_init_conflict(tmpdir, namespace_extensions, builtin_and_mock_packages, monkeypatch): """Test the view update logic in PythonPackage ignores conflicting instances of __init__ for packages which are in the same namespace. """ ext1_prefix, ext2_prefix, py_namespace = namespace_extensions python_spec = spack.spec.Spec('[email protected]') python_spec._concrete = True ext1_pkg = create_python_ext_pkg('py-extension1', ext1_prefix, python_spec, monkeypatch, py_namespace) ext2_pkg = create_python_ext_pkg('py-extension2', ext2_prefix, python_spec, monkeypatch, py_namespace) view_dir = str(tmpdir.join('view')) layout = DirectoryLayout(view_dir) view = YamlFilesystemView(view_dir, layout) python_pkg = python_spec.package python_pkg.activate(ext1_pkg, view) # Normally handled by Package.do_activate, but here we activate directly view.extensions_layout.add_extension(python_spec, ext1_pkg.spec) python_pkg.activate(ext2_pkg, view) f1 = 'lib/python2.7/site-packages/examplenamespace/ext1_sample.py' f2 = 'lib/python2.7/site-packages/examplenamespace/ext2_sample.py' init_file = 'lib/python2.7/site-packages/examplenamespace/__init__.py' assert os.path.exists(os.path.join(view_dir, f1)) assert os.path.exists(os.path.join(view_dir, f2)) assert os.path.exists(os.path.join(view_dir, init_file))
def deactivate(parser, args): specs = spack.cmd.parse_specs(args.spec) if len(specs) != 1: tty.die("deactivate requires one spec. %d given." % len(specs)) spec = spack.cmd.disambiguate_spec(specs[0]) pkg = spec.package if args.view: target = args.view elif pkg.is_extension: target = pkg.extendee_spec.prefix elif pkg.extendable: target = spec.prefix view = YamlFilesystemView(target, spack.store.layout) if args.all: if pkg.extendable: tty.msg("Deactivating all extensions of %s" % pkg.spec.short_spec) ext_pkgs = spack.store.db.activated_extensions_for( spec, view.extensions_layout) for ext_pkg in ext_pkgs: ext_pkg.spec.normalize() if ext_pkg.is_activated(view): ext_pkg.do_deactivate(view, force=True) elif pkg.is_extension: if not args.force and \ not spec.package.is_activated(view): tty.die("%s is not activated." % pkg.spec.short_spec) tty.msg("Deactivating %s and all dependencies." % pkg.spec.short_spec) topo_order = topological_sort(spec) index = spec.index() for name in topo_order: espec = index[name] epkg = espec.package if epkg.extends(pkg.extendee_spec): if epkg.is_activated(view) or args.force: epkg.do_deactivate(view, force=args.force) else: tty.die("spack deactivate --all requires an extendable package " "or an extension.") else: if not pkg.is_extension: tty.die("spack deactivate requires an extension.", "Did you mean 'spack deactivate --all'?") if not args.force and \ not spec.package.is_activated(view): tty.die("Package %s is not activated." % specs[0].short_spec) spec.package.do_deactivate(view, force=args.force)
def activate(parser, args): tty.warn("spack activate is deprecated in favor of " "environments and will be removed in v0.19.0") specs = spack.cmd.parse_specs(args.spec) if len(specs) != 1: tty.die("activate requires one spec. %d given." % len(specs)) spec = spack.cmd.disambiguate_spec(specs[0], ev.active_environment()) if not spec.package.is_extension: tty.die("%s is not an extension." % spec.name) if args.view: target = args.view else: target = spec.package.extendee_spec.prefix view = YamlFilesystemView(target, spack.store.layout) if spec.package.is_activated(view): tty.msg("Package %s is already activated." % specs[0].short_spec) return # TODO: refactor FilesystemView.add_extension and use that here (so there # aren't two ways of activating extensions) spec.package.do_activate(view, with_dependencies=not args.force)
def extensions(parser, args): if not args.spec: tty.die("extensions requires a package spec.") # Checks spec = cmd.parse_specs(args.spec) if len(spec) > 1: tty.die("Can only list extensions for one package.") if not spec[0].package.extendable: tty.die("%s is not an extendable package." % spec[0].name) env = ev.get_env(args, 'extensions') spec = cmd.disambiguate_spec(spec[0], env) if not spec.package.extendable: tty.die("%s does not have extensions." % spec.short_spec) if args.show in ("packages", "all"): # List package names of extensions extensions = spack.repo.path.extensions_for(spec) if not extensions: tty.msg("%s has no extensions." % spec.cshort_spec) else: tty.msg(spec.cshort_spec) tty.msg("%d extensions:" % len(extensions)) colify(ext.name for ext in extensions) if args.view: target = args.view else: target = spec.prefix view = YamlFilesystemView(target, spack.store.layout) if args.show in ("installed", "all"): # List specs of installed extensions. installed = [ s.spec for s in spack.store.db.installed_extensions_for(spec)] if args.show == "all": print if not installed: tty.msg("None installed.") else: tty.msg("%d installed:" % len(installed)) cmd.display_specs(installed, args) if args.show in ("activated", "all"): # List specs of activated extensions. activated = view.extensions_layout.extension_map(spec) if args.show == "all": print if not activated: tty.msg("None activated.") else: tty.msg("%d activated:" % len(activated)) cmd.display_specs(activated.values(), args)
def pre_uninstall(spec): pkg = spec.package assert spec.concrete if pkg.is_extension: target = pkg.extendee_spec.prefix view = YamlFilesystemView(target, spack.store.layout) if pkg.is_activated(view): # deactivate globally pkg.do_deactivate(force=True)
def activated_extensions_for(self, extendee_spec, extensions_layout=None): """ Return the specs of all packages that extend the given spec """ if extensions_layout is None: view = YamlFilesystemView(extendee_spec.prefix, spack.store.layout) extensions_layout = view.extensions_layout for spec in self.query(): try: extensions_layout.check_activated(extendee_spec, spec) yield spec.package except spack.directory_layout.NoSuchExtensionError: continue
def test_remove_extensions_ordered(install_mockery, mock_fetch, tmpdir): view_dir = str(tmpdir.join('view')) layout = YamlDirectoryLayout(view_dir) view = YamlFilesystemView(view_dir, layout) e2 = Spec('extension2').concretized() e2.package.do_install() view.add_specs(e2) e1 = e2['extension1'] view.remove_specs(e1, e2)
def test_perl_activation_view(tmpdir, perl_and_extension_dirs): perl_prefix, ext_prefix = perl_and_extension_dirs perl_spec = spack.spec.Spec('[email protected]') perl_spec._concrete = True perl_spec.package.spec.prefix = perl_prefix ext_pkg = FakeExtensionPackage('perl-extension', ext_prefix) view_dir = str(tmpdir.join('view')) layout = YamlDirectoryLayout(view_dir) view = YamlFilesystemView(view_dir, layout) perl_pkg = perl_spec.package perl_pkg.activate(ext_pkg, extensions_layout=view.extensions_layout) assert not os.path.exists(join_path(perl_prefix, 'bin/perl-ext-tool')) assert os.path.exists(join_path(view_dir, 'bin/perl-ext-tool'))
def test_python_activation_view(tmpdir, python_and_extension_dirs): python_prefix, ext_prefix = python_and_extension_dirs python_spec = spack.spec.Spec('[email protected]') python_spec._concrete = True python_spec.package.spec._set_test_prefix(python_prefix) ext_pkg = FakeExtensionPackage('py-extension', ext_prefix) view_dir = str(tmpdir.join('view')) layout = YamlDirectoryLayout(view_dir) view = YamlFilesystemView(view_dir, layout) python_pkg = python_spec.package python_pkg.activate(ext_pkg, extensions_layout=view.extensions_layout) assert not os.path.exists(join_path(python_prefix, 'bin/py-ext-tool')) assert os.path.exists(join_path(view_dir, 'bin/py-ext-tool'))
def test_perl_activation_view(tmpdir, perl_and_extension_dirs, builtin_and_mock_packages): perl_prefix, ext_prefix = perl_and_extension_dirs perl_spec = spack.spec.Spec('[email protected]') perl_spec._concrete = True perl_spec.package.spec.prefix = perl_prefix ext_pkg = create_ext_pkg('perl-extension', ext_prefix, perl_spec) view_dir = str(tmpdir.join('view')) layout = YamlDirectoryLayout(view_dir) view = YamlFilesystemView(view_dir, layout) perl_pkg = perl_spec.package perl_pkg.activate(ext_pkg, view) assert not os.path.exists(os.path.join(perl_prefix, 'bin/perl-ext-tool')) assert os.path.exists(os.path.join(view_dir, 'bin/perl-ext-tool'))
def test_python_activation_view(tmpdir, python_and_extension_dirs, builtin_and_mock_packages, monkeypatch): python_prefix, ext_prefix = python_and_extension_dirs python_spec = spack.spec.Spec('[email protected]') python_spec._concrete = True python_spec.package.spec.prefix = python_prefix ext_pkg = create_python_ext_pkg('py-extension1', ext_prefix, python_spec, monkeypatch) view_dir = str(tmpdir.join('view')) layout = DirectoryLayout(view_dir) view = YamlFilesystemView(view_dir, layout) python_pkg = python_spec.package python_pkg.activate(ext_pkg, view) assert not os.path.exists(os.path.join(python_prefix, 'bin/py-ext-tool')) assert os.path.exists(os.path.join(view_dir, 'bin/py-ext-tool'))
def test_python_keep_namespace_init(tmpdir, namespace_extensions, builtin_and_mock_packages): """Test the view update logic in PythonPackage keeps the namespace __init__ file as long as one package in the namespace still exists. """ ext1_prefix, ext2_prefix, py_namespace = namespace_extensions python_spec = spack.spec.Spec('[email protected]') python_spec._concrete = True ext1_pkg = create_python_ext_pkg('py-extension1', ext1_prefix, python_spec, py_namespace) ext2_pkg = create_python_ext_pkg('py-extension2', ext2_prefix, python_spec, py_namespace) view_dir = str(tmpdir.join('view')) layout = YamlDirectoryLayout(view_dir) view = YamlFilesystemView(view_dir, layout) python_pkg = python_spec.package python_pkg.activate(ext1_pkg, view) # Normally handled by Package.do_activate, but here we activate directly view.extensions_layout.add_extension(python_spec, ext1_pkg.spec) python_pkg.activate(ext2_pkg, view) view.extensions_layout.add_extension(python_spec, ext2_pkg.spec) f1 = 'lib/python2.7/site-packages/examplenamespace/ext1_sample.py' init_file = 'lib/python2.7/site-packages/examplenamespace/__init__.py' python_pkg.deactivate(ext1_pkg, view) view.extensions_layout.remove_extension(python_spec, ext1_pkg.spec) assert not os.path.exists(os.path.join(view_dir, f1)) assert os.path.exists(os.path.join(view_dir, init_file)) python_pkg.deactivate(ext2_pkg, view) view.extensions_layout.remove_extension(python_spec, ext2_pkg.spec) assert not os.path.exists(os.path.join(view_dir, init_file))
def activate(parser, args): specs = spack.cmd.parse_specs(args.spec) if len(specs) != 1: tty.die("activate requires one spec. %d given." % len(specs)) env = ev.get_env(args, 'activate') spec = spack.cmd.disambiguate_spec(specs[0], env) if not spec.package.is_extension: tty.die("%s is not an extension." % spec.name) if args.view: target = args.view else: target = spec.package.extendee_spec.prefix view = YamlFilesystemView(target, spack.store.layout) if spec.package.is_activated(view): tty.msg("Package %s is already activated." % specs[0].short_spec) return # TODO: refactor FilesystemView.add_extension and use that here (so there # aren't two ways of activating extensions) spec.package.do_activate(view, with_dependencies=not args.force)
def view(parser, args): 'Produce a view of a set of packages.' specs = spack.cmd.parse_specs(args.specs) path = args.path[0] if args.action in actions_link and args.projection_file: # argparse confirms file exists with open(args.projection_file, 'r') as f: projections_data = s_yaml.load(f) validate(projections_data, spack.schema.projections.schema) ordered_projections = projections_data['projections'] else: ordered_projections = {} # What method are we using for this view if args.action in ("hardlink", "hard"): link_fn = view_hardlink elif args.action in ("copy", "relocate"): link_fn = view_copy else: link_fn = view_symlink view = YamlFilesystemView(path, spack.store.layout, projections=ordered_projections, ignore_conflicts=getattr(args, "ignore_conflicts", False), link=link_fn, verbose=args.verbose) # Process common args and specs if getattr(args, "all", False): specs = view.get_all_specs() if len(specs) == 0: tty.warn("Found no specs in %s" % path) elif args.action in actions_link: # only link commands need to disambiguate specs env = ev.get_env(args, 'view link') specs = [spack.cmd.disambiguate_spec(s, env) for s in specs] elif args.action in actions_status: # no specs implies all if len(specs) == 0: specs = view.get_all_specs() else: specs = disambiguate_in_view(specs, view) else: # status and remove can map a partial spec to packages in view specs = disambiguate_in_view(specs, view) with_dependencies = args.dependencies.lower() in ['true', 'yes'] # Map action to corresponding functionality if args.action in actions_link: try: view.add_specs(*specs, with_dependencies=with_dependencies, exclude=args.exclude) except MergeConflictError: tty.info("Some file blocked the merge, adding the '-i' flag will " "ignore this conflict. For more information see e.g. " "https://github.com/spack/spack/issues/9029") raise elif args.action in actions_remove: view.remove_specs(*specs, with_dependencies=with_dependencies, exclude=args.exclude, with_dependents=not args.no_remove_dependents) elif args.action in actions_status: view.print_status(*specs, with_dependencies=with_dependencies) else: tty.error('Unknown action: "%s"' % args.action)
def view(self): return YamlFilesystemView(self.root, spack.store.layout, ignore_conflicts=True, projections=self.projections)
def extensions(parser, args): if not args.spec: tty.die("extensions requires a package spec.") show_packages = False show_installed = False show_activated = False show_all = False if args.show == 'packages': show_packages = True elif args.show == 'installed': show_installed = True elif args.show == 'activated': show_activated = True elif args.show == 'all': show_packages = True show_installed = True show_activated = True show_all = True else: tty.die('unrecognized show type: %s' % args.show) # # Checks # spec = spack.cmd.parse_specs(args.spec) if len(spec) > 1: tty.die("Can only list extensions for one package.") if not spec[0].package.extendable: tty.die("%s is not an extendable package." % spec[0].name) spec = spack.cmd.disambiguate_spec(spec[0]) if not spec.package.extendable: tty.die("%s does not have extensions." % spec.short_spec) if not args.mode: args.mode = 'short' if show_packages: # # List package names of extensions extensions = spack.repo.path.extensions_for(spec) if not extensions: tty.msg("%s has no extensions." % spec.cshort_spec) else: tty.msg(spec.cshort_spec) tty.msg("%d extensions:" % len(extensions)) colify(ext.name for ext in extensions) if args.view: target = args.view else: target = spec.prefix view = YamlFilesystemView(target, spack.store.layout) if show_installed: # # List specs of installed extensions. # installed = [ s.spec for s in spack.store.db.installed_extensions_for(spec) ] if show_all: print if not installed: tty.msg("None installed.") else: tty.msg("%d installed:" % len(installed)) spack.cmd.find.display_specs(installed, mode=args.mode) if show_activated: # # List specs of activated extensions. # activated = view.extensions_layout.extension_map(spec) if show_all: print if not activated: tty.msg("None activated.") else: tty.msg("%d currently activated:" % len(activated)) spack.cmd.find.display_specs(activated.values(), mode=args.mode, long=args.long)
def extensions(parser, args): if not args.spec: # If called without arguments, list all the extendable packages isatty = sys.stdout.isatty() if isatty: tty.info('Extendable packages:') extendable_pkgs = [] for name in spack.repo.all_package_names(): pkg = spack.repo.get(name) if pkg.extendable: extendable_pkgs.append(name) colify(extendable_pkgs, indent=4) return # Checks spec = cmd.parse_specs(args.spec) if len(spec) > 1: tty.die("Can only list extensions for one package.") if not spec[0].package.extendable: tty.die("%s is not an extendable package." % spec[0].name) env = ev.active_environment() spec = cmd.disambiguate_spec(spec[0], env) if not spec.package.extendable: tty.die("%s does not have extensions." % spec.short_spec) if args.show in ("packages", "all"): # List package names of extensions extensions = spack.repo.path.extensions_for(spec) if not extensions: tty.msg("%s has no extensions." % spec.cshort_spec) else: tty.msg(spec.cshort_spec) tty.msg("%d extensions:" % len(extensions)) colify(ext.name for ext in extensions) if args.view: target = args.view else: target = spec.prefix view = YamlFilesystemView(target, spack.store.layout) if args.show in ("installed", "all"): # List specs of installed extensions. installed = [ s.spec for s in spack.store.db.installed_extensions_for(spec) ] if args.show == "all": print if not installed: tty.msg("None installed.") else: tty.msg("%d installed:" % len(installed)) cmd.display_specs(installed, args) if args.show in ("activated", "all"): # List specs of activated extensions. activated = view.extensions_layout.extension_map(spec) if args.show == "all": print if not activated: tty.msg("None activated.") else: tty.msg("%d activated:" % len(activated)) cmd.display_specs(activated.values(), args)
def deactivate(parser, args): tty.warn("spack deactivate is deprecated in favor of " "environments and will be removed in v0.19.0") specs = spack.cmd.parse_specs(args.spec) if len(specs) != 1: tty.die("deactivate requires one spec. %d given." % len(specs)) env = ev.active_environment() spec = spack.cmd.disambiguate_spec(specs[0], env) pkg = spec.package if args.view: target = args.view elif pkg.is_extension: target = pkg.extendee_spec.prefix elif pkg.extendable: target = spec.prefix view = YamlFilesystemView(target, spack.store.layout) if args.all: if pkg.extendable: tty.msg("Deactivating all extensions of %s" % pkg.spec.short_spec) ext_pkgs = spack.store.db.activated_extensions_for( spec, view.extensions_layout) for ext_pkg in ext_pkgs: ext_pkg.spec.normalize() if ext_pkg.is_activated(view): ext_pkg.do_deactivate(view, force=True) elif pkg.is_extension: if not args.force and \ not spec.package.is_activated(view): tty.die("%s is not activated." % pkg.spec.short_spec) tty.msg("Deactivating %s and all dependencies." % pkg.spec.short_spec) nodes_in_topological_order = spack.graph.topological_sort(spec) for espec in reversed(nodes_in_topological_order): epkg = espec.package if epkg.extends(pkg.extendee_spec): if epkg.is_activated(view) or args.force: epkg.do_deactivate(view, force=args.force) else: tty.die( "spack deactivate --all requires an extendable package " "or an extension.") else: if not pkg.is_extension: tty.die("spack deactivate requires an extension.", "Did you mean 'spack deactivate --all'?") if not args.force and \ not spec.package.is_activated(view): tty.die("Package %s is not activated." % specs[0].short_spec) spec.package.do_deactivate(view, force=args.force)