def sort_yaml_obj(obj): if isinstance(obj, Mapping): return syaml.syaml_dict( (k, sort_yaml_obj(v)) for k, v in sorted(obj.items(), key=(lambda item: str(item[0])))) if isinstance(obj, Sequence) and not isinstance(obj, str): return syaml.syaml_list(sort_yaml_obj(x) for x in obj) return obj
def _mark_overrides(data): if isinstance(data, list): return syaml.syaml_list(_mark_overrides(elt) for elt in data) elif isinstance(data, dict): marked = syaml.syaml_dict() for key, val in iteritems(data): if isinstance(key, string_types) and key.endswith(':'): key = syaml.syaml_str(key[:-1]) key.override = True marked[key] = _mark_overrides(val) return marked else: return data
def _mark_internal(data, name): """Add a simple name mark to raw YAML/JSON data. This is used by `spack config blame` to show where config lines came from. """ if isinstance(data, dict): d = syaml.syaml_dict((_mark_internal(k, name), _mark_internal(v, name)) for k, v in data.items()) elif isinstance(data, list): d = syaml.syaml_list(_mark_internal(e, name) for e in data) else: d = syaml.syaml_type(data) if syaml.markable(d): d._start_mark = yaml.Mark(name, None, None, None, None, None) d._end_mark = yaml.Mark(name, None, None, None, None, None) return d
def export(parser, args): q_args = {"explicit": True if args.explicit else any} specs = args.specs(**q_args) # Exit early if no package matches the constraint if not args.specs and args.constraint: msg = "No package matches the query: {0}" msg = msg.format(' '.join(args.constraint)) tty.msg(msg) return packages = spack.config.get('packages', scope=args.scope) # 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) specs = [x for x in specs if x.name in packages_with_tags] if args.exclude: specs = set(filter_exclude(specs, args.exclude)) cls = None if args.module: cls = spack.modules.module_types[args.module] # Collect packages per package name pkgs = {} for spec in specs: pkgs.setdefault(spec.name, []).append(spec) pymods = {} # Dump per package, make sure that none are forgotten for pkg, pkg_specs in pkgs.items(): paths = syaml_dict() modules = syaml_dict() package = packages.setdefault(pkg, syaml_dict()) versions = None if 'version' in package: versions = [str(v) for v in package['version']] for spec in pkg_specs: key = spec.format(args.format) sflags = [] bflags = [] for k, v in spec.variants.items(): default = None if k in spec.package.variants: default = spec.package.variants[k].default if v.value != default or args.variants == 'all': if v.value in (True, False): bflags.append(v) elif v.name != 'patches': sflags.append(v) sflags = ' '.join(str(f) for f in sorted(sflags)) bflags = ''.join(str(f) for f in sorted(bflags)) key = ' '.join([e for e in (key, sflags, bflags) if len(e) > 0]) key = str(key) if isinstance(spec.package, PythonPackage): py = spec['python'] if args.dependencies: key += " ^{0}".format(py.format("$_$@")) if not spec.package.is_activated(py.package.view()): # For external packages, setup_environment is not # called, and thus they are not included in # PYTHON_PATH. msg = "python package not activated, skipping: {0}" msg = msg.format(spec.format("$_$@")) tty.warn(msg) # paths[key] = str(spec.prefix) else: mod = pymods.setdefault(py, cls(py) if cls else None) if mod and not mod.conf.blacklisted: if os.path.exists(mod.layout.filename): paths[key] = '/activated' # modules[key] = mod.layout.use_name # paths[key] = str(spec.prefix) else: msg = "python package activated in inactive module, skipping: {0}" msg = msg.format(spec.format("$_$@")) tty.warn(msg) continue else: mod = cls(spec) if cls else None if mod and not mod.conf.blacklisted: if os.path.exists(mod.layout.filename): modules[key] = str(mod.layout.use_name) else: msg = "module not present for {0}" msg = msg.format(spec.format("$_$@")) tty.warn(msg) # Even with modules, the path needs to be present to, e.g., # have `spack setup` work! paths.setdefault(key, []).append(spec) if versions and str(spec.version) not in versions: versions.append(str(spec.version)) if versions: package['version'] = syaml_list(sorted(versions, reverse=True)) if len(paths) > 0: def install_date(s): _, record = spack.store.db.query_by_spec_hash(s.dag_hash()) return record.installation_time for k in paths.keys(): values = paths[k] if values == '/activated': continue paths[k] = str( sorted(values, key=install_date, reverse=True)[0].prefix) package.setdefault('paths', syaml_dict()).update(paths) if len(modules) > 0: package.setdefault('modules', syaml_dict()).update(modules) # Trim empty items from the yaml for cfg in packages.values(): for k, v in list(cfg.items()): if (k == 'buildable' and v) or (hasattr(v, '__iter__') and len(v) == 0): del cfg[k] # Restore ordering packages = syaml_dict( sorted((k, v) for (k, v) in packages.items() if len(v) > 0)) if 'all' in packages: packages['all'] = packages.pop('all') yaml.dump({'packages': packages}, stream=sys.stdout, default_flow_style=False, Dumper=PackagesDumper)
def export(parser, args): q_args = {"explicit": True if args.explicit else any} specs = args.specs(**q_args) # Exit early if no package matches the constraint if not args.specs and args.constraint: msg = "No package matches the query: {0}" msg = msg.format(' '.join(args.constraint)) tty.msg(msg) return packages = spack.config.get('packages', scope=args.scope) # 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) specs = [x for x in specs if x.name in packages_with_tags] if args.exclude: specs = set(filter_exclude(specs, args.exclude)) cls = None if args.module: cls = spack.modules.module_types[args.module] # Add all selected specs to the external packages new_packages = {} for spec in specs: pkg_toplevel = new_packages.setdefault(spec.name, {}) pkg_externals = pkg_toplevel.setdefault("externals", []) pkg_versions = pkg_toplevel.setdefault("version", syaml_list()) key = _to_key(spec, args.format, args.variants) externality = dict(spec=key, prefix=str(spec.prefix)) if key in [ext["spec"] for ext in pkg_externals]: tty.warn("spec already present, skipping: {0}".format(key)) continue mod = cls(spec, 'default') if cls else None if mod and not mod.conf.blacklisted: if os.path.exists(mod.layout.filename): externality["modules"] = [str(mod.layout.use_name)] else: msg = "module not present for {0}" msg = msg.format(spec.format("$_$@")) tty.warn(msg) version = str(spec.version) if version not in pkg_versions: pkg_versions.append(version) pkg_externals.append(externality) spack.config.merge_yaml(packages, new_packages) # Restore ordering packages = syaml_dict( sorted((k, v) for (k, v) in packages.items() if len(v) > 0)) for pkg in args.unbuildable: packages.setdefault(pkg, {})['buildable'] = False if 'all' in packages: packages['all'] = packages.pop('all') yaml.dump({'packages': packages}, stream=sys.stdout, default_flow_style=False, Dumper=PackagesDumper)