def ensure_valid_license_family(meta): try: license_family = meta['about']['license_family'] except KeyError: return if license_family not in allowed_license_families: raise RuntimeError(exceptions.indent("""about/license_family '%s' not allowed. Allowed families are %s.""" % (license_family, comma_join(sorted(allowed_license_families)))))
def ensure_valid_license_family(meta): try: license_family = meta['about']['license_family'] except KeyError: return if (remove_special_characters(normalize(license_family)) not in allowed_license_families): raise RuntimeError(exceptions.indent( "about/license_family '%s' not allowed. Allowed families are %s." % (license_family, comma_join(sorted(allowed_license_families)))))
def inspect_linkages(packages, prefix=sys.prefix, untracked=False, all_packages=False, show_files=False, groupby="package"): pkgmap = {} installed = _installed(prefix) if not packages and not untracked and not all_packages: raise ValueError("At least one package or --untracked or --all must be provided") if all_packages: packages = sorted(installed.keys()) if untracked: packages.append(untracked_package) for pkg in packages: if pkg == untracked_package: dist = untracked_package elif pkg not in installed: sys.exit("Package %s is not installed in %s" % (pkg, prefix)) else: dist = installed[pkg] if not sys.platform.startswith(('linux', 'darwin')): sys.exit("Error: conda inspect linkages is only implemented in Linux and OS X") if dist == untracked_package: obj_files = get_untracked_obj_files(prefix) else: obj_files = get_package_obj_files(dist, prefix) linkages = get_linkages(obj_files, prefix) depmap = defaultdict(list) pkgmap[pkg] = depmap depmap['not found'] = [] depmap['system'] = [] for binary in linkages: for lib, path in linkages[binary]: path = replace_path(binary, path, prefix) if path not in {'', 'not found'} else path if path.startswith(prefix): deps = list(which_package(path)) if len(deps) > 1: deps_str = [str(dep) for dep in deps] get_logger(__name__).warn("Warning: %s comes from multiple " "packages: %s", path, comma_join(deps_str)) if not deps: if exists(path): depmap['untracked'].append((lib, path.split(prefix + '/', 1)[-1], binary)) else: depmap['not found'].append((lib, path.split(prefix + '/', 1)[-1], binary)) for d in deps: depmap[d].append((lib, path.split(prefix + '/', 1)[-1], binary)) elif path == 'not found': depmap['not found'].append((lib, path, binary)) else: depmap['system'].append((lib, path, binary)) output_string = "" if groupby == 'package': for pkg in packages: output_string += _underlined_text(pkg) output_string += print_linkages(pkgmap[pkg], show_files=show_files) elif groupby == 'dependency': # {pkg: {dep: [files]}} -> {dep: {pkg: [files]}} inverted_map = defaultdict(lambda: defaultdict(list)) for pkg in pkgmap: for dep in pkgmap[pkg]: if pkgmap[pkg][dep]: inverted_map[dep][pkg] = pkgmap[pkg][dep] # print system and not found last k = sorted(set(inverted_map.keys()) - {'system', 'not found'}) for dep in k + ['system', 'not found']: output_string += _underlined_text(dep) output_string += print_linkages(inverted_map[dep], show_files=show_files) else: raise ValueError("Unrecognized groupby: %s" % groupby) if hasattr(output_string, 'decode'): output_string = output_string.decode('utf-8') return output_string
def inspect_linkages(packages, prefix=sys.prefix, untracked=False, all_packages=False, show_files=False, groupby="package", sysroot=""): pkgmap = {} installed = _installed(prefix) if not packages and not untracked and not all_packages: raise ValueError( "At least one package or --untracked or --all must be provided") if all_packages: packages = sorted(installed.keys()) if untracked: packages.append(untracked_package) for pkg in ensure_list(packages): if pkg == untracked_package: dist = untracked_package elif pkg not in installed: sys.exit("Package %s is not installed in %s" % (pkg, prefix)) else: dist = installed[pkg] if not sys.platform.startswith(('linux', 'darwin')): sys.exit( "Error: conda inspect linkages is only implemented in Linux and OS X" ) if dist == untracked_package: obj_files = get_untracked_obj_files(prefix) else: obj_files = get_package_obj_files(dist, prefix) linkages = get_linkages(obj_files, prefix, sysroot) depmap = defaultdict(list) pkgmap[pkg] = depmap depmap['not found'] = [] depmap['system'] = [] for binary in linkages: for lib, path in linkages[binary]: path = replace_path(binary, path, prefix) if path not in { '', 'not found' } else path if path.startswith(prefix): in_prefix_path = re.sub('^' + prefix + '/', '', path) deps = list(which_package(in_prefix_path, prefix)) if len(deps) > 1: deps_str = [str(dep) for dep in deps] get_logger(__name__).warn( "Warning: %s comes from multiple " "packages: %s", path, comma_join(deps_str)) if not deps: if exists(path): depmap['untracked'].append( (lib, path.split(prefix + '/', 1)[-1], binary)) else: depmap['not found'].append( (lib, path.split(prefix + '/', 1)[-1], binary)) for d in deps: depmap[d].append((lib, path.split(prefix + '/', 1)[-1], binary)) elif path == 'not found': depmap['not found'].append((lib, path, binary)) else: depmap['system'].append((lib, path, binary)) output_string = "" if groupby == 'package': for pkg in packages: output_string += _underlined_text(pkg) output_string += print_linkages(pkgmap[pkg], show_files=show_files) elif groupby == 'dependency': # {pkg: {dep: [files]}} -> {dep: {pkg: [files]}} inverted_map = defaultdict(lambda: defaultdict(list)) for pkg in pkgmap: for dep in pkgmap[pkg]: if pkgmap[pkg][dep]: inverted_map[dep][pkg] = pkgmap[pkg][dep] # print system and not found last k = sorted(set(inverted_map.keys()) - {'system', 'not found'}) for dep in k + ['system', 'not found']: output_string += _underlined_text(dep) output_string += print_linkages(inverted_map[dep], show_files=show_files) else: raise ValueError("Unrecognized groupby: %s" % groupby) if hasattr(output_string, 'decode'): output_string = output_string.decode('utf-8') return output_string
def create_info_files(m, files, include_recipe=True): ''' Creates the metadata files that will be stored in the built package. :param m: Package metadata :type m: Metadata :param files: Paths to files to include in package :type files: list of str :param include_recipe: Whether or not to include the recipe (True by default) :type include_recipe: bool ''' if not isdir(config.info_dir): os.makedirs(config.info_dir) if include_recipe: recipe_dir = join(config.info_dir, 'recipe') os.makedirs(recipe_dir) for fn in os.listdir(m.path): if fn.startswith('.'): continue src_path = join(m.path, fn) dst_path = join(recipe_dir, fn) if isdir(src_path): shutil.copytree(src_path, dst_path) else: shutil.copy(src_path, dst_path) license_file = m.get_value('about/license_file') if license_file: filenames = 'LICENSE', 'LICENSE.txt', 'license', 'license.txt' if license_file is True: for fn in filenames: src = join(source.get_dir(), fn) if isfile(src): break else: sys.exit("Error: could not locate license file (any of " "%s) in: %s" % (comma_join(filenames), source.get_dir())) else: src = join(source.get_dir(), license_file) shutil.copy(src, join(config.info_dir, 'license.txt')) readme = m.get_value('about/readme') if readme: src = join(source.get_dir(), readme) if not isfile(src): sys.exit("Error: no readme file: %s" % readme) dst = join(config.info_dir, readme) shutil.copy(src, dst) if os.path.split(readme)[1] not in {"README.md", "README.rst", "README"}: print("WARNING: anaconda.org only recognizes about/readme as README.md and README.rst", file=sys.stderr) # Deal with Python 2 and 3's different json module type reqs mode_dict = {'mode': 'w', 'encoding': 'utf-8'} if PY3 else {'mode': 'wb'} with open(join(config.info_dir, 'index.json'), **mode_dict) as fo: json.dump(m.info_index(), fo, indent=2, sort_keys=True) if include_recipe: with open(join(config.info_dir, 'recipe.json'), **mode_dict) as fo: json.dump(m.meta, fo, indent=2, sort_keys=True) if sys.platform == 'win32': # make sure we use '/' path separators in metadata files = [f.replace('\\', '/') for f in files] with open(join(config.info_dir, 'files'), 'w') as fo: if m.get_value('build/noarch_python'): fo.write('\n') else: for f in files: fo.write(f + '\n') files_with_prefix = sorted(have_prefix_files(files)) binary_has_prefix_files = m.binary_has_prefix_files() text_has_prefix_files = m.has_prefix_files() if files_with_prefix and not m.get_value('build/noarch_python'): auto_detect = m.get_value('build/detect_binary_files_with_prefix') if sys.platform == 'win32': # Paths on Windows can contain spaces, so we need to quote the # paths. Fortunately they can't contain quotes, so we don't have # to worry about nested quotes. fmt_str = '"%s" %s "%s"\n' else: # Don't do it everywhere because paths on Unix can contain quotes, # and we don't have a good method of escaping, and because older # versions of conda don't support quotes in has_prefix fmt_str = '%s %s %s\n' with open(join(config.info_dir, 'has_prefix'), 'w') as fo: for pfix, mode, fn in files_with_prefix: if (fn in text_has_prefix_files): # register for text replacement, regardless of mode fo.write(fmt_str % (pfix, 'text', fn)) text_has_prefix_files.remove(fn) elif ((mode == 'binary') and (fn in binary_has_prefix_files)): print("Detected hard-coded path in binary file %s" % fn) fo.write(fmt_str % (pfix, mode, fn)) binary_has_prefix_files.remove(fn) elif (auto_detect or (mode == 'text')): print("Detected hard-coded path in %s file %s" % (mode, fn)) fo.write(fmt_str % (pfix, mode, fn)) else: print("Ignored hard-coded path in %s" % fn) # make sure we found all of the files expected errstr = "" for f in text_has_prefix_files: errstr += "Did not detect hard-coded path in %s from has_prefix_files\n" % f for f in binary_has_prefix_files: errstr += "Did not detect hard-coded path in %s from binary_has_prefix_files\n" % f if errstr: raise RuntimeError(errstr) no_link = m.get_value('build/no_link') if no_link: if not isinstance(no_link, list): no_link = [no_link] with open(join(config.info_dir, 'no_link'), 'w') as fo: for f in files: if any(fnmatch.fnmatch(f, p) for p in no_link): fo.write(f + '\n') if m.get_value('source/git_url'): with io.open(join(config.info_dir, 'git'), 'w', encoding='utf-8') as fo: source.git_info(fo) if m.get_value('app/icon'): shutil.copyfile(join(m.path, m.get_value('app/icon')), join(config.info_dir, 'icon.png'))
def create_info_files(m, files, include_recipe=True): ''' Creates the metadata files that will be stored in the built package. :param m: Package metadata :type m: Metadata :param files: Paths to files to include in package :type files: list of str :param include_recipe: Whether or not to include the recipe (True by default) :type include_recipe: bool ''' if not isdir(config.info_dir): os.makedirs(config.info_dir) if include_recipe: recipe_dir = join(config.info_dir, 'recipe') os.makedirs(recipe_dir) for fn in os.listdir(m.path): if fn.startswith('.'): continue src_path = join(m.path, fn) dst_path = join(recipe_dir, fn) if isdir(src_path): shutil.copytree(src_path, dst_path) else: shutil.copy(src_path, dst_path) license_file = m.get_value('about/license_file') if license_file: filenames = 'LICENSE', 'LICENSE.txt', 'license', 'license.txt' if license_file is True: for fn in filenames: src = join(source.get_dir(), fn) if isfile(src): break else: sys.exit("Error: could not locate license file (any of " "%s) in: %s" % (comma_join(filenames), source.get_dir())) else: src = join(source.get_dir(), license_file) shutil.copy(src, join(config.info_dir, 'license.txt')) readme = m.get_value('about/readme') if readme: src = join(source.get_dir(), readme) if not isfile(src): sys.exit("Error: no readme file: %s" % readme) dst = join(config.info_dir, readme) shutil.copy(src, dst) if os.path.split(readme)[1] not in { "README.md", "README.rst", "README" }: print( "WARNING: anaconda.org only recognizes about/readme as README.md and README.rst", file=sys.stderr) # Deal with Python 2 and 3's different json module type reqs mode_dict = {'mode': 'w', 'encoding': 'utf-8'} if PY3 else {'mode': 'wb'} with open(join(config.info_dir, 'index.json'), **mode_dict) as fo: json.dump(m.info_index(), fo, indent=2, sort_keys=True) if include_recipe: with open(join(config.info_dir, 'recipe.json'), **mode_dict) as fo: json.dump(m.meta, fo, indent=2, sort_keys=True) if sys.platform == 'win32': # make sure we use '/' path separators in metadata files = [f.replace('\\', '/') for f in files] with open(join(config.info_dir, 'files'), 'w') as fo: if m.get_value('build/noarch_python'): fo.write('\n') else: for f in files: fo.write(f + '\n') files_with_prefix = sorted(have_prefix_files(files)) binary_has_prefix_files = m.binary_has_prefix_files() text_has_prefix_files = m.has_prefix_files() if files_with_prefix and not m.get_value('build/noarch_python'): auto_detect = m.get_value('build/detect_binary_files_with_prefix') if sys.platform == 'win32': # Paths on Windows can contain spaces, so we need to quote the # paths. Fortunately they can't contain quotes, so we don't have # to worry about nested quotes. fmt_str = '"%s" %s "%s"\n' else: # Don't do it everywhere because paths on Unix can contain quotes, # and we don't have a good method of escaping, and because older # versions of conda don't support quotes in has_prefix fmt_str = '%s %s %s\n' with open(join(config.info_dir, 'has_prefix'), 'w') as fo: for pfix, mode, fn in files_with_prefix: if (fn in text_has_prefix_files): # register for text replacement, regardless of mode fo.write(fmt_str % (pfix, 'text', fn)) text_has_prefix_files.remove(fn) elif ((mode == 'binary') and (fn in binary_has_prefix_files)): print("Detected hard-coded path in binary file %s" % fn) fo.write(fmt_str % (pfix, mode, fn)) binary_has_prefix_files.remove(fn) elif (auto_detect or (mode == 'text')): print("Detected hard-coded path in %s file %s" % (mode, fn)) fo.write(fmt_str % (pfix, mode, fn)) else: print("Ignored hard-coded path in %s" % fn) # make sure we found all of the files expected errstr = "" for f in text_has_prefix_files: errstr += "Did not detect hard-coded path in %s from has_prefix_files\n" % f for f in binary_has_prefix_files: errstr += "Did not detect hard-coded path in %s from binary_has_prefix_files\n" % f if errstr: raise RuntimeError(errstr) no_link = m.get_value('build/no_link') if no_link: if not isinstance(no_link, list): no_link = [no_link] with open(join(config.info_dir, 'no_link'), 'w') as fo: for f in files: if any(fnmatch.fnmatch(f, p) for p in no_link): fo.write(f + '\n') if m.get_value('source/git_url'): with io.open(join(config.info_dir, 'git'), 'w', encoding='utf-8') as fo: source.git_info(fo) if m.get_value('app/icon'): shutil.copyfile(join(m.path, m.get_value('app/icon')), join(config.info_dir, 'icon.png'))
def execute(args, parser): if not args.subcommand: parser.print_help() exit() prefix = get_prefix(args) installed = ci.linked(prefix) if not args.packages and not args.untracked and not args.all: parser.error("At least one package or --untracked or --all must be provided") if args.all: args.packages = sorted([i.rsplit('-', 2)[0] for i in installed]) if args.untracked: args.packages.append(untracked_package) if args.subcommand == 'linkages': pkgmap = {} for pkg in args.packages: if pkg == untracked_package: dist = untracked_package else: for dist in installed: if pkg == dist.rsplit('-', 2)[0]: break else: sys.exit("Package %s is not installed in %s" % (pkg, prefix)) if not sys.platform.startswith(('linux', 'darwin')): sys.exit("Error: conda inspect linkages is only implemented in Linux and OS X") if dist == untracked_package: obj_files = get_untracked_obj_files(prefix) else: obj_files = get_package_obj_files(dist, prefix) linkages = get_linkages(obj_files, prefix) depmap = defaultdict(list) pkgmap[pkg] = depmap depmap['not found'] = [] for binary in linkages: for lib, path in linkages[binary]: path = replace_path(binary, path, prefix) if path not in {'', 'not found'} else path if path.startswith(prefix): deps = list(which_package(path)) if len(deps) > 1: print("Warning: %s comes from multiple packages: %s" % (path, comma_join(deps)), file=sys.stderr) if not deps: if exists(path): depmap['untracked'].append((lib, path.split(prefix + '/', 1)[-1], binary)) else: depmap['not found'].append((lib, path.split(prefix + '/', 1)[-1], binary)) for d in deps: depmap[d].append((lib, path.split(prefix + '/', 1)[-1], binary)) elif path == 'not found': depmap['not found'].append((lib, path, binary)) else: depmap['system'].append((lib, path, binary)) if args.groupby == 'package': for pkg in args.packages: print(pkg) print('-'*len(str(pkg))) print() print_linkages(pkgmap[pkg], show_files=args.show_files) elif args.groupby == 'dependency': # {pkg: {dep: [files]}} -> {dep: {pkg: [files]}} inverted_map = defaultdict(lambda: defaultdict(list)) for pkg in pkgmap: for dep in pkgmap[pkg]: if pkgmap[pkg][dep]: inverted_map[dep][pkg] = pkgmap[pkg][dep] # print system and not found last k = sorted(set(inverted_map.keys()) - {'system', 'not found'}) for dep in k + ['system', 'not found']: print(dep) print('-'*len(str(dep))) print() print_linkages(inverted_map[dep], show_files=args.show_files) else: raise ValueError("Unrecognized groupby: %s" % args.groupby) if args.subcommand == 'objects': for pkg in args.packages: if pkg == untracked_package: dist = untracked_package else: for dist in installed: if pkg == dist.rsplit('-', 2)[0]: break else: sys.exit("Package %s is not installed in %s" % (pkg, prefix)) print(pkg) print('-'*len(str(pkg))) print() if not sys.platform.startswith('darwin'): sys.exit("Error: conda inspect objects is only implemented in OS X") if dist == untracked_package: obj_files = get_untracked_obj_files(prefix) else: obj_files = get_package_obj_files(dist, prefix) info = [] for f in obj_files: f_info = {} path = join(prefix, f) f_info['filetype'] = human_filetype(path) f_info['rpath'] = ':'.join(get_rpaths(path)) f_info['filename'] = f info.append(f_info) print_object_info(info, args.groupby)
def execute(args, parser): if not args.subcommand: parser.print_help() exit() prefix = get_prefix(args) installed = ci.linked(prefix) if not args.packages and not args.untracked and not args.all: parser.error( "At least one package or --untracked or --all must be provided") if args.all: args.packages = sorted([i.rsplit('-', 2)[0] for i in installed]) if args.untracked: args.packages.append(untracked_package) if args.subcommand == 'linkages': pkgmap = {} for pkg in args.packages: if pkg == untracked_package: dist = untracked_package else: for dist in installed: if pkg == dist.rsplit('-', 2)[0]: break else: sys.exit("Package %s is not installed in %s" % (pkg, prefix)) if not sys.platform.startswith(('linux', 'darwin')): sys.exit( "Error: conda inspect linkages is only implemented in Linux and OS X" ) if dist == untracked_package: obj_files = get_untracked_obj_files(prefix) else: obj_files = get_package_obj_files(dist, prefix) linkages = get_linkages(obj_files, prefix) depmap = defaultdict(list) pkgmap[pkg] = depmap depmap['not found'] = [] for binary in linkages: for lib, path in linkages[binary]: path = replace_path(binary, path, prefix) if path not in { '', 'not found' } else path if path.startswith(prefix): deps = list(which_package(path)) if len(deps) > 1: print( "Warning: %s comes from multiple packages: %s" % (path, comma_join(deps)), file=sys.stderr) if not deps: if exists(path): depmap['untracked'].append( (lib, path.split(prefix + '/', 1)[-1], binary)) else: depmap['not found'].append( (lib, path.split(prefix + '/', 1)[-1], binary)) for d in deps: depmap[d].append((lib, path.split(prefix + '/', 1)[-1], binary)) elif path == 'not found': depmap['not found'].append((lib, path, binary)) else: depmap['system'].append((lib, path, binary)) if args.groupby == 'package': for pkg in args.packages: print(pkg) print('-' * len(str(pkg))) print() print_linkages(pkgmap[pkg], show_files=args.show_files) elif args.groupby == 'dependency': # {pkg: {dep: [files]}} -> {dep: {pkg: [files]}} inverted_map = defaultdict(lambda: defaultdict(list)) for pkg in pkgmap: for dep in pkgmap[pkg]: if pkgmap[pkg][dep]: inverted_map[dep][pkg] = pkgmap[pkg][dep] # print system and not found last k = sorted(set(inverted_map.keys()) - {'system', 'not found'}) for dep in k + ['system', 'not found']: print(dep) print('-' * len(str(dep))) print() print_linkages(inverted_map[dep], show_files=args.show_files) else: raise ValueError("Unrecognized groupby: %s" % args.groupby) if args.subcommand == 'objects': for pkg in args.packages: if pkg == untracked_package: dist = untracked_package else: for dist in installed: if pkg == dist.rsplit('-', 2)[0]: break else: sys.exit("Package %s is not installed in %s" % (pkg, prefix)) print(pkg) print('-' * len(str(pkg))) print() if not sys.platform.startswith('darwin'): sys.exit( "Error: conda inspect objects is only implemented in OS X") if dist == untracked_package: obj_files = get_untracked_obj_files(prefix) else: obj_files = get_package_obj_files(dist, prefix) info = [] for f in obj_files: f_info = {} path = join(prefix, f) f_info['filetype'] = human_filetype(path) f_info['rpath'] = ':'.join(get_rpaths(path)) f_info['filename'] = f info.append(f_info) print_object_info(info, args.groupby)