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 graph(parser, args): if args.installed: if args.specs: tty.die("Can't specify specs with --installed") args.dot = True env = ev.active_environment() if env: specs = env.all_specs() else: specs = spack.store.db.query() else: specs = spack.cmd.parse_specs(args.specs, concretize=not args.static) if not specs: setup_parser.parser.print_help() return 1 if args.static: args.dot = True if args.dot: graph_dot(specs, static=args.static, deptype=args.deptype) elif specs: # ascii is default: user doesn't need to provide it explicitly debug = spack.config.get('config:debug') graph_ascii(specs[0], debug=debug, deptype=args.deptype) for spec in specs[1:]: print() # extra line bt/w independent graphs graph_ascii(spec, debug=debug)
def deactivate(): """ Deactivate an environment and collect corresponding environment modifications Returns: spack.util.environment.EnvironmentModifications: Environment variables modifications to activate environment. """ env_mods = EnvironmentModifications() active = ev.active_environment() if active is None: return env_mods if ev.default_view_name in active.views: try: with spack.store.db.read_transaction(): active.rm_default_view_from_env(env_mods) except (spack.repo.UnknownPackageError, spack.repo.UnknownNamespaceError) as e: tty.warn(e) tty.warn('Could not fully deactivate view due to missing package ' 'or repo, shell environment may be corrupt.') ev.deactivate() return env_mods
def deactivate(): """ Deactivate an environment and collect corresponding environment modifications. Note: unloads the environment in its current state, not in the state it was loaded in, meaning that specs that were removed from the spack environment after activation are not unloaded. Returns: spack.util.environment.EnvironmentModifications: Environment variables modifications to activate environment. """ env_mods = EnvironmentModifications() active = ev.active_environment() if active is None: return env_mods if ev.default_view_name in active.views: try: with spack.store.db.read_transaction(): active.rm_default_view_from_env(env_mods) except (spack.repo.UnknownPackageError, spack.repo.UnknownNamespaceError) as e: tty.warn(e) tty.warn('Could not fully deactivate view due to missing package ' 'or repo, shell environment may be corrupt.') ev.deactivate() return env_mods
def deprecate(parser, args): """Deprecate one spec in favor of another""" env = ev.active_environment() specs = spack.cmd.parse_specs(args.specs) if len(specs) != 2: raise SpackError('spack deprecate requires exactly two specs') install_query = [InstallStatuses.INSTALLED, InstallStatuses.DEPRECATED] deprecate = spack.cmd.disambiguate_spec(specs[0], env, local=True, installed=install_query) if args.install: deprecator = specs[1].concretized() else: deprecator = spack.cmd.disambiguate_spec(specs[1], env, local=True) # calculate all deprecation pairs for errors and warning message all_deprecate = [] all_deprecators = [] generator = deprecate.traverse( order='post', type='link', root=True) if args.dependencies else [deprecate] for spec in generator: all_deprecate.append(spec) all_deprecators.append(deprecator[spec.name]) # This will throw a key error if deprecator does not have a dep # that matches the name of a dep of the spec if not args.yes_to_all: tty.msg('The following packages will be deprecated:\n') spack.cmd.display_specs(all_deprecate, **display_args) tty.msg("In favor of (respectively):\n") spack.cmd.display_specs(all_deprecators, **display_args) print() already_deprecated = [] already_deprecated_for = [] for spec in all_deprecate: deprecated_for = spack.store.db.deprecator(spec) if deprecated_for: already_deprecated.append(spec) already_deprecated_for.append(deprecated_for) tty.msg('The following packages are already deprecated:\n') spack.cmd.display_specs(already_deprecated, **display_args) tty.msg('In favor of (respectively):\n') spack.cmd.display_specs(already_deprecated_for, **display_args) answer = tty.get_yes_or_no('Do you want to proceed?', default=False) if not answer: tty.die('Will not deprecate any packages.') link_fn = os.link if args.link_type == 'hard' else os.symlink for dcate, dcator in zip(all_deprecate, all_deprecators): dcate.package.do_deprecate(dcator, link_fn)
def gc(parser, args): specs = spack.store.db.unused_specs # Restrict garbage collection to the active environment # speculating over roots that are yet to be installed env = ev.active_environment() if env: msg = 'Restricting the garbage collection to the "{0}" environment' tty.msg(msg.format(env.name)) env.concretize() roots = [s for s in env.roots()] all_hashes = set([s.dag_hash() for r in roots for s in r.traverse()]) lr_hashes = set([ s.dag_hash() for r in roots for s in r.traverse(deptype=('link', 'run')) ]) maybe_to_be_removed = all_hashes - lr_hashes specs = [s for s in specs if s.dag_hash() in maybe_to_be_removed] if not specs: msg = "There are no unused specs. Spack's store is clean." tty.msg(msg) return if not args.yes_to_all: spack.cmd.uninstall.confirm_removal(specs) spack.cmd.uninstall.do_uninstall(None, specs, force=False)
def test_list(args): """List installed packages with available tests.""" tagged = set(spack.repo.path.packages_with_tags(*args.tag)) if args.tag \ else set() def has_test_and_tags(pkg_class): return has_test_method(pkg_class) and \ (not args.tag or pkg_class.name in tagged) if args.list_all: report_packages = [ pkg_class.name for pkg_class in spack.repo.path.all_package_classes() if has_test_and_tags(pkg_class) ] if sys.stdout.isatty(): filtered = ' tagged' if args.tag else '' tty.msg("{0}{1} packages with tests.". format(len(report_packages), filtered)) colify.colify(report_packages) return # TODO: This can be extended to have all of the output formatting options # from `spack find`. env = ev.active_environment() hashes = env.all_hashes() if env else None specs = spack.store.db.query(hashes=hashes) specs = list(filter(lambda s: has_test_and_tags(s.package_class), specs)) spack.cmd.display_specs(specs, long=True)
def dependents(parser, args): specs = spack.cmd.parse_specs(args.spec) if len(specs) != 1: tty.die("spack dependents takes only one spec.") if args.installed: env = ev.active_environment() spec = spack.cmd.disambiguate_spec(specs[0], env) format_string = '{name}{@version}{%compiler}{/hash:7}' if sys.stdout.isatty(): tty.msg("Dependents of %s" % spec.cformat(format_string)) deps = spack.store.db.installed_relatives(spec, 'parents', args.transitive) if deps: spack.cmd.display_specs(deps, long=True) else: print("No dependents") else: spec = specs[0] ideps = inverted_dependencies() dependents = get_dependents(spec.name, ideps, args.transitive) dependents.remove(spec.name) if dependents: colify(sorted(dependents)) else: print("No dependents")
def test_run(args): """Run tests for the specified installed packages. If no specs are listed, run tests for all packages in the current environment or all installed packages if there is no active environment. """ # cdash help option if args.help_cdash: parser = argparse.ArgumentParser( formatter_class=argparse.RawDescriptionHelpFormatter, epilog=textwrap.dedent('''\ environment variables: SPACK_CDASH_AUTH_TOKEN authentication token to present to CDash ''')) arguments.add_cdash_args(parser, True) parser.print_help() return # set config option for fail-fast if args.fail_fast: spack.config.set('config:fail_fast', True, scope='command_line') # Get specs to test env = ev.active_environment() hashes = env.all_hashes() if env else None specs = spack.cmd.parse_specs(args.specs) if args.specs else [None] specs_to_test = [] for spec in specs: matching = spack.store.db.query_local(spec, hashes=hashes) if spec and not matching: tty.warn("No installed packages match spec %s" % spec) specs_to_test.extend(matching) # test_stage_dir test_suite = spack.install_test.TestSuite(specs_to_test, args.alias) test_suite.ensure_stage() tty.msg("Spack test %s" % test_suite.name) # Set up reporter setattr(args, 'package', [s.format() for s in test_suite.specs]) reporter = spack.report.collect_info(spack.package.PackageBase, 'do_test', args.log_format, args) if not reporter.filename: if args.log_file: if os.path.isabs(args.log_file): log_file = args.log_file else: log_dir = os.getcwd() log_file = os.path.join(log_dir, args.log_file) else: log_file = os.path.join(os.getcwd(), 'test-%s' % test_suite.name) reporter.filename = log_file reporter.specs = specs_to_test with reporter('test', test_suite.stage): test_suite(remove_directory=not args.keep_stage, dirty=args.dirty, fail_first=args.fail_first)
def substitute_config_variables(path): """Substitute placeholders into paths. Spack allows paths in configs to have some placeholders, as follows: - $env The active Spack environment. - $spack The Spack instance's prefix - $tempdir Default temporary directory returned by tempfile.gettempdir() - $user The current user's username - $user_cache_path The user cache directory (~/.spack, unless overridden) These are substituted case-insensitively into the path, and users can use either ``$var`` or ``${var}`` syntax for the variables. $env is only replaced if there is an active environment, and should only be used in environment yaml files. """ import spack.environment as ev # break circular env = ev.active_environment() if env: replacements.update({'env': env.path}) else: # If a previous invocation added env, remove it replacements.pop('env', None) # Look up replacements def repl(match): m = match.group(0).strip('${}') return replacements.get(m.lower(), match.group(0)) # Replace $var or ${var}. return re.sub(r'(\$\w+\b|\$\{\w+\})', repl, path)
def load(parser, args): env = ev.active_environment() if args.list: results = spack.cmd.filter_loaded_specs(args.specs()) if sys.stdout.isatty(): spack.cmd.print_how_many_pkgs(results, "loaded") spack.cmd.display_specs(results) return specs = [spack.cmd.disambiguate_spec(spec, env, first=args.load_first) for spec in spack.cmd.parse_specs(args.constraint)] if not args.shell: specs_str = ' '.join(args.constraint) or "SPECS" spack.cmd.common.shell_init_instructions( "spack load", " eval `spack load {sh_arg} %s`" % specs_str, ) return 1 with spack.store.db.read_transaction(): if 'dependencies' in args.things_to_load: include_roots = 'package' in args.things_to_load specs = [dep for spec in specs for dep in spec.traverse(root=include_roots, order='post')] env_mod = spack.util.environment.EnvironmentModifications() for spec in specs: env_mod.extend(uenv.environment_modifications_for_spec(spec)) env_mod.prepend_path(uenv.spack_loaded_hashes_var, spec.dag_hash()) cmds = env_mod.shell_modifications(args.shell) sys.stdout.write(cmds)
def assemble_dict_of_detected_externals(env, black_list, white_list): external_spec_dict = {} active_env = ev.active_environment() def update_dictionary(env, spec): if spec.name in external_spec_dict: external_spec_dict[spec.name].append( create_external_detected_spec(env, spec)) else: external_spec_dict[spec.name] = [ create_external_detected_spec(env, spec) ] for spec in env.all_specs(): if spec.external: continue if black_list: if spec.name not in black_list: update_dictionary(env, spec) elif white_list: if spec.name in white_list: update_dictionary(env, spec) else: if not active_env.is_develop(spec): update_dictionary(env, spec) return external_spec_dict
def analyze(parser, args, **kwargs): # If the user wants to list analyzers, do so and exit if args.analyze_command == "list-analyzers": spack.analyzers.list_all() sys.exit(0) # handle active environment, if any env = ev.active_environment() # Get an disambiguate spec (we should only have one) specs = spack.cmd.parse_specs(args.spec) if not specs: tty.die("You must provide one or more specs to analyze.") spec = spack.cmd.disambiguate_spec(specs[0], env) # The user wants to monitor builds using github.com/spack/spack-monitor # It is instantianted once here, and then available at spack.monitor.cli monitor = None if args.use_monitor: monitor = spack.monitor.get_client( host=args.monitor_host, prefix=args.monitor_prefix, ) # Run the analysis analyze_spec(spec, args.analyzers, args.path, monitor, args.overwrite)
def spec(parser, args): name_fmt = '{namespace}.{name}' if args.namespaces else '{name}' fmt = '{@version}{%compiler}{compiler_flags}{variants}{arch=architecture}' install_status_fn = spack.spec.Spec.install_status tree_kwargs = { 'cover': args.cover, 'format': name_fmt + fmt, 'hashlen': None if args.very_long else 7, 'show_types': args.types, 'status_fn': install_status_fn if args.install_status else None } # use a read transaction if we are getting install status for every # spec in the DAG. This avoids repeatedly querying the DB. tree_context = lang.nullcontext if args.install_status: tree_context = spack.store.db.read_transaction # Use command line specified specs, otherwise try to use environment specs. if args.specs: input_specs = spack.cmd.parse_specs(args.specs) specs = [(s, s.concretized()) for s in input_specs] else: env = ev.active_environment() if env: env.concretize() specs = env.concretized_specs() else: tty.die( "spack spec requires at least one spec or an active environment" ) for (input, output) in specs: # With -y, just print YAML to output. if args.format: # The user can specify the hash type to use hash_type = getattr(ht, args.hash_type) if args.format == 'yaml': # use write because to_yaml already has a newline. sys.stdout.write(output.to_yaml(hash=hash_type)) else: print(output.to_json(hash=hash_type)) continue with tree_context(): # Only show the headers for input specs that are not concrete to avoid # repeated output. This happens because parse_specs outputs concrete # specs for `/hash` inputs. if not input.concrete: tree_kwargs['hashes'] = False # Always False for input spec print("Input spec") print("--------------------------------") print(input.tree(**tree_kwargs)) print("Concretized") print("--------------------------------") tree_kwargs['hashes'] = args.long or args.very_long print(output.tree(**tree_kwargs))
def post_install(spec): import spack.environment as ev # break import cycle if ev.active_environment(): # If the installed through an environment, we skip post_install # module generation and generate the modules on env_write so Spack # can manage interactions between env views and modules return _for_each_enabled(spec, 'write')
def createtarball(args): """create a binary package from an existing install""" # restrict matching to current environment if one is active env = ev.active_environment() output_location = None if args.directory: output_location = args.directory # User meant to provide a path to a local directory. # Ensure that they did not accidentally pass a URL. scheme = url_util.parse(output_location, scheme='<missing>').scheme if scheme != '<missing>': raise ValueError( '"--directory" expected a local path; got a URL, instead') # User meant to provide a path to a local directory. # Ensure that the mirror lookup does not mistake it for a named mirror. output_location = 'file://' + output_location elif args.mirror_name: output_location = args.mirror_name # User meant to provide the name of a preconfigured mirror. # Ensure that the mirror lookup actually returns a named mirror. result = spack.mirror.MirrorCollection().lookup(output_location) if result.name == "<unnamed>": raise ValueError('no configured mirror named "{name}"'.format( name=output_location)) elif args.mirror_url: output_location = args.mirror_url # User meant to provide a URL for an anonymous mirror. # Ensure that they actually provided a URL. scheme = url_util.parse(output_location, scheme='<missing>').scheme if scheme == '<missing>': raise ValueError( '"{url}" is not a valid URL'.format(url=output_location)) add_spec = ('package' in args.things_to_install) add_deps = ('dependencies' in args.things_to_install) _createtarball(env, spec_yaml=args.spec_yaml, packages=args.specs, add_spec=add_spec, add_deps=add_deps, output_location=output_location, signing_key=args.key, force=args.force, make_relative=args.rel, unsigned=args.unsigned, allow_root=args.allow_root, rebuild_index=args.rebuild_index)
def matching_spec_from_env(spec): """ Returns a concrete spec, matching what is available in the environment. If no matching spec is found in the environment (or if no environment is active), this will return the given spec but concretized. """ env = ev.active_environment() if env: return env.matching_spec(spec) or spec.concretized() else: return spec.concretized()
def verify(parser, args): local = args.local if args.type == 'files': if args.all: setup_parser.parser.print_help() return 1 for file in args.specs_or_files: results = spack.verify.check_file_manifest(file) if results.has_errors(): if args.json: print(results.json_string()) else: print(results) return 0 else: spec_args = spack.cmd.parse_specs(args.specs_or_files) if args.all: query = spack.store.db.query_local if local else spack.store.db.query # construct spec list if spec_args: spec_list = spack.cmd.parse_specs(args.specs_or_files) specs = [] for spec in spec_list: specs += query(spec, installed=True) else: specs = query(installed=True) elif args.specs_or_files: # construct disambiguated spec list env = ev.active_environment() specs = list( map(lambda x: spack.cmd.disambiguate_spec(x, env, local=local), spec_args)) else: setup_parser.parser.print_help() return 1 for spec in specs: tty.debug("Verifying package %s") results = spack.verify.check_spec_manifest(spec) if results.has_errors(): if args.json: print(results.json_string()) else: tty.msg("In package %s" % spec.format('{name}/{hash:7}')) print(results) return 1 else: tty.debug(results)
def env_status(args): env = ev.active_environment() if env: if env.path == os.getcwd(): tty.msg('Using %s in current directory: %s' % (ev.manifest_name, env.path)) else: tty.msg('In environment %s' % env.name) # Check if environment views can be safely activated env.check_views() else: tty.msg('No active environment')
def env_view(args): env = ev.active_environment() if env: if args.action == ViewAction.regenerate: env.regenerate_views() elif args.action == ViewAction.enable: if args.view_path: view_path = args.view_path else: view_path = env.view_path_default env.update_default_view(view_path) env.write() elif args.action == ViewAction.disable: env.update_default_view(None) env.write() else: tty.msg("No active environment")
def fetch(parser, args): if args.specs: specs = spack.cmd.parse_specs(args.specs, concretize=True) else: # No specs were given explicitly, check if we are in an # environment. If yes, check the missing argument, if yes # fetch all uninstalled specs from it otherwise fetch all. # If we are also not in an environment, complain to the # user that we don't know what to do. env = ev.active_environment() if env: if args.missing: specs = env.uninstalled_specs() else: specs = env.all_specs() if specs == []: tty.die("No uninstalled specs in environment. Did you " "run `spack concretize` yet?") else: tty.die("fetch requires at least one spec argument") if args.no_checksum: spack.config.set("config:checksum", False, scope="command_line") if args.deprecated: spack.config.set('config:deprecated', True, scope='command_line') for spec in specs: if args.missing or args.dependencies: for s in spec.traverse(): package = spack.repo.get(s) # Skip already-installed packages with --missing if args.missing and package.installed: continue # Do not attempt to fetch externals (they're local) if package.spec.external: continue package.do_fetch() package = spack.repo.get(spec) package.do_fetch()
def env_deactivate(args): if not args.shell: spack.cmd.common.shell_init_instructions( "spack env deactivate", " eval `spack env deactivate {sh_arg}`", ) return 1 # Error out when -e, -E, -D flags are given, cause they are ambiguous. if args.env or args.no_env or args.env_dir: tty.die('Calling spack env deactivate with --env, --env-dir and --no-env ' 'is ambiguous') if ev.active_environment() is None: tty.die('No environment is currently active.') cmds = spack.environment.shell.deactivate_header(args.shell) env_mods = spack.environment.shell.deactivate() cmds += env_mods.shell_modifications(args.shell) sys.stdout.write(cmds)
def _matching_specs(args): """Return a list of matching specs read from either a spec file (JSON or YAML), a query over the store or a query over the active environment. """ env = ev.active_environment() hashes = env.all_hashes() if env else None if args.spec_file: return spack.store.specfile_matches(args.spec_file, hashes=hashes) if args.specs: constraints = spack.cmd.parse_specs(args.specs) return spack.store.find(constraints, hashes=hashes) if env: return [env.specs_by_hash[h] for h in env.concretized_order] tty.die("build cache file creation requires at least one" + " installed package spec, an active environment," + " or else a path to a json or yaml file containing a spec" + " to install")
def require_active_env(cmd_name): """Used by commands to get the active environment If an environment is not found, print an error message that says the calling command *needs* an active environment. Arguments: cmd_name (str): name of calling command Returns: (spack.environment.Environment): the active environment """ env = ev.active_environment() if env: return env else: tty.die('`spack %s` requires an environment' % cmd_name, 'activate an environment first:', ' spack env activate ENV', 'or use:', ' spack -e ENV %s ...' % cmd_name)
def _find(parser, args): q_args = query_arguments(args) results = args.specs(**q_args) env = ev.active_environment() decorator = lambda s, f: f if env: decorator, _, roots, _ = setup_env(env) # use groups by default except with format. if args.groups is None: args.groups = not args.format # Exit early with an error code if no package matches the constraint if not results and args.constraint: msg = "No package matches the query: {0}" msg = msg.format(' '.join(args.constraint)) tty.msg(msg) raise SystemExit(1) # If tags have been specified on the command line, filter by tags if args.tags: packages_with_tags = spack.repo.path.packages_with_tags(*args.tags) results = [x for x in results if x.name in packages_with_tags] if args.loaded: results = spack.cmd.filter_loaded_specs(results) # Display the result if args.json: cmd.display_specs_as_json(results, deps=args.deps) else: if not args.format: if env: display_env(env, args, decorator) if sys.stdout.isatty() and args.groups: pkg_type = "loaded" if args.loaded else "installed" spack.cmd.print_how_many_pkgs(results, pkg_type) cmd.display_specs(results, args, decorator=decorator, all_headers=True)
def diff(parser, args): env = ev.active_environment() if len(args.specs) != 2: tty.die("You must provide two specs to diff.") specs = [spack.cmd.disambiguate_spec(spec, env, first=args.load_first) for spec in spack.cmd.parse_specs(args.specs)] # Calculate the comparison (c) color = False if args.dump_json else get_color_when() c = compare_specs(specs[0], specs[1], to_string=True, color=color) # Default to all attributes attributes = args.attribute or ["all"] if args.dump_json: print(sjson.dump(c)) else: tty.warn("This interface is subject to change.\n") print_difference(c, attributes)
def _specs(self, **kwargs): qspecs = spack.cmd.parse_specs(self.values) # If an environment is provided, we'll restrict the search to # only its installed packages. env = ev.active_environment() if env: kwargs['hashes'] = set(env.all_hashes()) # return everything for an empty query. if not qspecs: return spack.store.db.query(**kwargs) # Return only matching stuff otherwise. specs = {} for spec in qspecs: for s in spack.store.db.query(spec, **kwargs): # This is fast for already-concrete specs specs[s.dag_hash()] = s return sorted(specs.values())
def stage(parser, args): # We temporarily modify the working directory when setting up a stage, so we need to # convert this to an absolute path here in order for it to remain valid later. custom_path = os.path.abspath(args.path) if args.path else None if custom_path: spack.stage.create_stage_root(custom_path) if not args.specs: env = ev.active_environment() if env: tty.msg("Staging specs from environment %s" % env.name) for spec in env.specs_by_hash.values(): for dep in spec.traverse(): dep.package.do_stage() tty.msg("Staged {0} in {1}".format(dep.package.name, dep.package.stage.path)) return else: tty.die("`spack stage` requires a spec or an active environment") if args.no_checksum: spack.config.set('config:checksum', False, scope='command_line') if args.deprecated: spack.config.set('config:deprecated', True, scope='command_line') specs = spack.cmd.parse_specs(args.specs, concretize=False) # prevent multiple specs from extracting in the same folder if len(specs) > 1 and custom_path: tty.die("`--path` requires a single spec, but multiple were provided") for spec in specs: spec = spack.cmd.matching_spec_from_env(spec) package = spack.repo.get(spec) if custom_path: package.path = custom_path package.do_stage() tty.msg("Staged {0} in {1}".format(package.name, package.stage.path))
def test_list(args): """List installed packages with available tests.""" if args.list_all: all_packages_with_tests = [ pkg_class.name for pkg_class in spack.repo.path.all_package_classes() if has_test_method(pkg_class) ] if sys.stdout.isatty(): tty.msg("%d packages with tests." % len(all_packages_with_tests)) colify.colify(all_packages_with_tests) return # TODO: This can be extended to have all of the output formatting options # from `spack find`. env = ev.active_environment() hashes = env.all_hashes() if env else None specs = spack.store.db.query(hashes=hashes) specs = list(filter(lambda s: has_test_method(s.package_class), specs)) spack.cmd.display_specs(specs, long=True)
def _get_scope_and_section(args): """Extract config scope and section from arguments.""" scope = args.scope section = getattr(args, 'section', None) path = getattr(args, 'path', None) # w/no args and an active environment, point to env manifest if not section: env = ev.active_environment() if env: scope = env.env_file_config_scope_name() # set scope defaults elif not scope: scope = spack.config.default_modify_scope(section) # special handling for commands that take value instead of section if path: section = path[:path.find(':')] if ':' in path else path if not scope: scope = spack.config.default_modify_scope(section) return scope, section