コード例 #1
0
ファイル: metadata.py プロジェクト: frol/conda-build
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)))))
コード例 #2
0
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)))))
コード例 #3
0
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)))))
コード例 #4
0
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)))))
コード例 #5
0
ファイル: inspect.py プロジェクト: timsnyder/conda-build
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
コード例 #6
0
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
コード例 #7
0
ファイル: build.py プロジェクト: frol/conda-build
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'))
コード例 #8
0
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'))
コード例 #9
0
ファイル: main_inspect.py プロジェクト: frol/conda-build
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)
コード例 #10
0
ファイル: main_inspect.py プロジェクト: frol/conda-build
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)