Exemple #1
0
    def test_channel(self):
        d = Dist.from_string("conda-forge::spyder-app-2.3.8-py27_0.tar.bz2")
        assert d.channel == 'conda-forge'
        assert d.quad[0] == "spyder-app"
        assert d.dist_name == "spyder-app-2.3.8-py27_0"

        d = Dist.from_string("s3://some/bucket/name::spyder-app-2.3.8-py27_0.tar.bz2")
        assert d.channel == 's3://some/bucket/name'
        assert d.quad[0] == "spyder-app"
        assert d.dist_name == "spyder-app-2.3.8-py27_0"
Exemple #2
0
    def test_channel(self):
        d = Dist.from_string("conda-forge::spyder-app-2.3.8-py27_0.tar.bz2")
        assert d.channel == 'conda-forge'
        assert d.quad[0] == "spyder-app"
        assert d.dist_name == "spyder-app-2.3.8-py27_0"

        d = Dist.from_string(
            "s3://some/bucket/name::spyder-app-2.3.8-py27_0.tar.bz2")
        assert d.channel == 's3://some/bucket/name'
        assert d.quad[0] == "spyder-app"
        assert d.dist_name == "spyder-app-2.3.8-py27_0"
Exemple #3
0
def test_channel(fmt):
    d = Dist.from_string("conda-forge::spyder-app-2.3.8-py27_0{}".format(fmt))
    assert d.channel == 'conda-forge'
    assert d.quad[0] == "spyder-app"
    assert d.dist_name == "spyder-app-2.3.8-py27_0"
    assert d.fmt == fmt

    d = Dist.from_string("s3://some/bucket/name::spyder-app-2.3.8-py27_0{}".format(fmt))
    assert d.channel == 's3://some/bucket/name'
    assert d.quad[0] == "spyder-app"
    assert d.dist_name == "spyder-app-2.3.8-py27_0"
    assert d.to_url() == join_url("s3://some/bucket/name", context.subdir,
                                    "spyder-app-2.3.8-py27_0{}".format(fmt))
Exemple #4
0
 def setUp(self):
     self.index = {
         Dist.from_string("test1-1", channel_override="defaults"):
             generate_mocked_package(None, "test1", "default", "1.0.1"),
         Dist.from_string("test1-1", channel_override="rando_chnl"):
             generate_mocked_package("env", "test1", "default", "2.1.4"),
         Dist.from_string("test2-2", channel_override="defaults"):
             generate_mocked_package("env", "test2", "default", "1.1.1"),
         Dist.from_string("test3-3", channel_override="defaults"):
             generate_mocked_package(None, "test3", "default", "1.2.0"),
         Dist.from_string("test4-4", channel_override="defaults"):
             generate_mocked_package(None, "test4", "default", "1.2.1")
     }
     self.res = generate_mocked_resolve(None, self.index)
Exemple #5
0
 def test_simply_adds_unlink_on_non_windows(self):
     actions = {}
     dist = Dist.from_string(self.generate_random_dist())
     with self.mock_platform(windows=False):
         plan.add_unlink(actions, dist)
     self.assertIn(inst.UNLINK, actions)
     self.assertEqual(actions[inst.UNLINK], [dist, ])
Exemple #6
0
 def test_simply_adds_unlink_on_non_windows(self):
     actions = {}
     dist = Dist.from_string(self.generate_random_dist())
     with self.mock_platform(windows=False):
         plan.add_unlink(actions, dist)
     self.assertIn(inst.UNLINK, actions)
     self.assertEqual(actions[inst.UNLINK], [dist, ])
Exemple #7
0
    def test_dist(self):
        d = Dist.from_string("spyder-app-2.3.8-py27_0.tar.bz2")
        assert d.channel == UNKNOWN_CHANNEL
        assert d.quad[0] == "spyder-app"
        assert d.quad[1] == "2.3.8"
        assert d.quad[2] == "py27_0"
        assert d.build_number == 0
        assert d.dist_name == "spyder-app-2.3.8-py27_0"

        assert d == Dist.from_string("spyder-app-2.3.8-py27_0")
        assert d != Dist.from_string("spyder-app-2.3.8-py27_1.tar.bz2")

        d2 = Dist("spyder-app-2.3.8-py27_0.tar.bz2")
        assert d == d2

        d3 = Dist(d2)
        assert d3 is d2
Exemple #8
0
    def test_dist(self):
        d = Dist.from_string("spyder-app-2.3.8-py27_0.tar.bz2")
        assert d.channel == UNKNOWN_CHANNEL
        assert d.quad[0] == "spyder-app"
        assert d.quad[1] == "2.3.8"
        assert d.quad[2] == "py27_0"
        assert d.build_number == 0
        assert d.dist_name == "spyder-app-2.3.8-py27_0"

        assert d == Dist.from_string("spyder-app-2.3.8-py27_0")
        assert d != Dist.from_string("spyder-app-2.3.8-py27_1.tar.bz2")

        d2 = Dist("spyder-app-2.3.8-py27_0.tar.bz2")
        assert d == d2

        d3 = Dist(d2)
        assert d3 is d2
Exemple #9
0
def conda_lock(specification: schema.CondaSpecification,
               conda_exe: str = "mamba"):
    from conda_lock.conda_lock import run_lock
    from conda.models.dist import Dist

    with tempfile.TemporaryDirectory() as tmpdir:
        environment_path = pathlib.Path(tmpdir) / "environment.yaml"
        lockfile_path = pathlib.Path(tmpdir) / "environment-lock.yaml"

        with environment_path.open("w") as f:
            f.write(specification.json())

        try:
            run_lock(
                environment_files=[environment_path],
                platforms=[conda_platform()],
                lockfile_path=lockfile_path,
                conda_exe=conda_exe,
            )
        except subprocess.CalledProcessError as e:
            raise ValueError(e.output)

        with lockfile_path.open() as f:
            lockfile = yaml.safe_load(f)

    conda_packages = []
    pip_packages = []

    for package in lockfile["package"]:
        if package["manager"] == "conda":
            dist = Dist.from_string(package["url"])
            conda_packages.append({
                "name": dist.name,
                "build": dist.build,
                "build_number": dist.build_number,
                "constrains": None,
                "depends": [],
                "license": None,
                "license_family": None,
                "size": -1,
                "subdir": dist.subdir,
                "timestamp": None,
                "version": dist.version,
                "channel_id": dist.base_url,
                "md5": package["hash"].get("md5"),
                "sha256": package["hash"].get("sha256", ""),
                "summary": None,
                "description": None,
            })
        elif package["manager"] == "pip":
            pip_packages.append({
                "name": package["name"],
                "url": package["url"],
                "version": package["version"],
                "sha256": package["hash"]["sha256"],
            })

    return {"conda": conda_packages, "pip": pip_packages}
Exemple #10
0
def test_dist(fmt):
    d = Dist.from_string("spyder-app-2.3.8-py27_0{}".format(fmt))
    assert d.channel == UNKNOWN_CHANNEL
    assert d.quad[0] == "spyder-app"
    assert d.quad[1] == "2.3.8"
    assert d.quad[2] == "py27_0"
    assert d.build_number == 0
    assert d.dist_name == "spyder-app-2.3.8-py27_0"
    assert d.fmt == fmt

    assert d == Dist.from_string("spyder-app-2.3.8-py27_0")
    assert d != Dist.from_string("spyder-app-2.3.8-py27_1{}".format(fmt))

    d2 = Dist("spyder-app-2.3.8-py27_0{}".format(fmt))
    assert d == d2

    d3 = Dist(d2)
    assert d3 is d2
Exemple #11
0
 def setUp(self):
     pkgs = {
         "test-spec": [generate_mocked_package("test1", "test-spec", "defaults", "1"),
                       generate_mocked_package(None, "test-spec", "defaults", "3"),
                       generate_mocked_package(None, "test-spec", "defaults", "2"),
                       generate_mocked_package("ranenv", "test-spec", "rando_chnl", "5")],
         "test-spec2": [generate_mocked_package(None, "test-spec2", "defaults", "1")],
         "no-exist": [generate_mocked_package(None, "no-exist", "nope", "1")]
     }
     index = {
         Dist.from_string("test-spec", channel_override="defaults"):
             generate_mocked_package(None, "test-spec", "default", "1"),
         Dist.from_string("test-spec", channel_override="rando_chnl"):
             generate_mocked_package("ranenv", "test-spec", "default", "5"),
         Dist.from_string("test-spec2", channel_override="defaults"):
             generate_mocked_package("test1", "test-spec2", "default", "1")
     }
     self.res = generate_mocked_resolve(pkgs, index)
     self.specs = [MatchSpec("test-spec"), MatchSpec("test-spec2")]
Exemple #12
0
    def test_with_feature_depends(self):
        d = Dist.from_string("spyder-app-2.3.8-py27_0[mkl]")
        assert d.with_features_depends == "mkl"

        d = Dist("mkl@")
        assert d.channel == "@"
        assert d.quad[0] == "mkl@"
        assert d.quad[1] == ""
        assert d.quad[2] == ""
        assert d.with_features_depends is None
        assert d.is_feature_package
Exemple #13
0
    def test_with_feature_depends(self):
        d = Dist.from_string("spyder-app-2.3.8-py27_0[mkl]")
        assert d.with_features_depends == "mkl"

        d = Dist("mkl@")
        assert d.channel == "@"
        assert d.quad[0] == "mkl@"
        assert d.quad[1] == ""
        assert d.quad[2] == ""
        assert d.with_features_depends is None
        assert d.is_feature_package
Exemple #14
0
def generate_mocked_resolve(pkgs, install=None):
    mock_package = namedtuple(
        "IndexRecord", ["preferred_env", "name", "schannel", "version", "fn"])
    mock_resolve = namedtuple("Resolve", [
        "get_dists_for_spec", "index", "explicit", "install", "package_name",
        "dependency_sort"
    ])

    index = {}
    groups = defaultdict(list)
    for preferred_env, name, schannel, version in pkgs:
        dist = Dist.from_string('%s-%s-0' % (name, version),
                                channel_override=schannel)
        pkg = mock_package(preferred_env=preferred_env,
                           name=name,
                           schannel=schannel,
                           version=version,
                           fn=name)
        groups[name].append(dist)
        index[dist] = pkg

    def get_dists_for_spec(spec, emptyok=False):
        # Here, spec should be a MatchSpec
        res = groups[spec.name]
        if not res and not emptyok:
            raise NoPackagesFoundError([(spec, )])
        return res

    def get_explicit(spec):
        return True

    def get_install(spec, installed, update_deps=None):
        return install

    def get_package_name(dist):
        return dist.name

    def get_dependency_sort(specs):
        return tuple(spec for spec in specs.values())

    return mock_resolve(get_dists_for_spec=get_dists_for_spec,
                        index=index,
                        explicit=get_explicit,
                        install=get_install,
                        package_name=get_package_name,
                        dependency_sort=get_dependency_sort)
Exemple #15
0
def create_env(repo, pkgs, target):
    with Locked(target):
        spec_fname = os.path.join(repo.working_dir, 'env.spec')
        with open(spec_fname, 'r') as fh:
            spec = yaml.safe_load(fh)

        channels = prioritize_channels(spec.get('channels', []))
        # Build reverse look-up from channel URL to channel name.
        channel_by_url = {url: channel for url, (channel, _) in channels.items()}
        index = fetch_index(channels, use_cache=False)
        resolver = Resolve(index)
        # Create the package distribution from the manifest. Ensure to replace
        # channel-URLs with channel names, otherwise the fetch-extract may fail.
        dists = [Dist.from_string(pkg, channel_override=channel_by_url.get(url, url)) for url, pkg in pkgs]
        # Use the resolver to sort packages into the appropriate dependency
        # order.
        sorted_dists = resolver.dependency_sort({dist.name: dist for dist in dists})

        pfe = ProgressiveFetchExtract(index, sorted_dists)
        pfe.execute()
        mkdir_p(target)
        txn = UnlinkLinkTransaction.create_from_dists(index, target, (), sorted_dists)
        txn.execute()
Exemple #16
0
def generate_mocked_resolve(pkgs, install=None):
    mock_package = namedtuple("IndexRecord",
                              ["preferred_env", "name", "schannel", "version", "fn"])
    mock_resolve = namedtuple("Resolve", ["get_dists_for_spec", "index", "explicit", "install",
                                          "package_name", "dependency_sort"])

    index = {}
    groups = defaultdict(list)
    for preferred_env, name, schannel, version in pkgs:
        dist = Dist.from_string('%s-%s-0' % (name, version), channel_override=schannel)
        pkg = mock_package(preferred_env=preferred_env, name=name, schannel=schannel,
                           version=version, fn=name)
        groups[name].append(dist)
        index[dist] = pkg

    def get_dists_for_spec(spec, emptyok=False):
        # Here, spec should be a MatchSpec
        res = groups[spec.name]
        if not res and not emptyok:
            raise NoPackagesFoundError([(spec,)])
        return res

    def get_explicit(spec):
        return True

    def get_install(spec, installed, update_deps=None):
        return install

    def get_package_name(dist):
        return dist.name

    def get_dependency_sort(specs):
        return tuple(spec for spec in specs.values())

    return mock_resolve(get_dists_for_spec=get_dists_for_spec, index=index, explicit=get_explicit,
                        install=get_install, package_name=get_package_name,
                        dependency_sort=get_dependency_sort)
Exemple #17
0
def solve(specs):
    return [Dist.from_string(fn) for fn in r.solve(specs)]
Exemple #18
0
def test_display_actions_0():
    os.environ['CONDA_SHOW_CHANNEL_URLS'] = 'False'
    reset_context(())
    actions = defaultdict(
        list,
        {"FETCH": [Dist('sympy-0.7.2-py27_0'),
                   Dist("numpy-1.7.1-py27_0")]})
    # The older test index doesn't have the size metadata
    d = Dist.from_string('sympy-0.7.2-py27_0.tar.bz2')
    index[d] = IndexRecord.from_objects(index[d], size=4374752)
    d = Dist.from_string("numpy-1.7.1-py27_0.tar.bz2")
    index[d] = IndexRecord.from_objects(index[d], size=5994338)

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    sympy-0.7.2                |           py27_0         4.2 MB
    numpy-1.7.1                |           py27_0         5.7 MB
    ------------------------------------------------------------
                                           Total:         9.9 MB

"""

    actions = defaultdict(
        list, {
            'PREFIX':
            '/Users/aaronmeurer/anaconda/envs/test',
            'SYMLINK_CONDA': ['/Users/aaronmeurer/anaconda'],
            'LINK': [
                'python-3.3.2-0', 'readline-6.2-0 1', 'sqlite-3.7.13-0 1',
                'tk-8.5.13-0 1', 'zlib-1.2.7-0 1'
            ]
        })

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """Package plan for environment '/Users/aaronmeurer/anaconda/envs/test':

The following NEW packages will be INSTALLED:

    python:   3.3.2-0 \n\
    readline: 6.2-0   \n\
    sqlite:   3.7.13-0
    tk:       8.5.13-0
    zlib:     1.2.7-0 \n\

"""

    actions['UNLINK'] = actions['LINK']
    actions['LINK'] = []

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """Package plan for environment '/Users/aaronmeurer/anaconda/envs/test':

The following packages will be REMOVED:

    python:   3.3.2-0 \n\
    readline: 6.2-0   \n\
    sqlite:   3.7.13-0
    tk:       8.5.13-0
    zlib:     1.2.7-0 \n\

"""

    actions = defaultdict(list, {
        'LINK': ['cython-0.19.1-py33_0'],
        'UNLINK': ['cython-0.19-py33_0']
    })

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be UPDATED:

    cython: 0.19-py33_0 --> 0.19.1-py33_0

"""

    actions['LINK'], actions['UNLINK'] = actions['UNLINK'], actions['LINK']

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be DOWNGRADED:

    cython: 0.19.1-py33_0 --> 0.19-py33_0

"""

    actions = defaultdict(
        list, {
            'LINK': [
                'cython-0.19.1-py33_0', 'dateutil-1.5-py33_0',
                'numpy-1.7.1-py33_0'
            ],
            'UNLINK':
            ['cython-0.19-py33_0', 'dateutil-2.1-py33_1', 'pip-1.3.1-py33_1']
        })

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following NEW packages will be INSTALLED:

    numpy:    1.7.1-py33_0

The following packages will be REMOVED:

    pip:      1.3.1-py33_1

The following packages will be UPDATED:

    cython:   0.19-py33_0  --> 0.19.1-py33_0

The following packages will be DOWNGRADED:

    dateutil: 2.1-py33_1   --> 1.5-py33_0   \n\

"""

    actions = defaultdict(
        list, {
            'LINK': ['cython-0.19.1-py33_0', 'dateutil-2.1-py33_1'],
            'UNLINK': ['cython-0.19-py33_0', 'dateutil-1.5-py33_0']
        })

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be UPDATED:

    cython:   0.19-py33_0 --> 0.19.1-py33_0
    dateutil: 1.5-py33_0  --> 2.1-py33_1   \n\

"""

    actions['LINK'], actions['UNLINK'] = actions['UNLINK'], actions['LINK']

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
Exemple #19
0
 def test_adds_to_existing_actions(self):
     actions = {inst.UNLINK: [{"foo": "bar"}]}
     dist = Dist.from_string(self.generate_random_dist())
     with self.mock_platform(windows=False):
         plan.add_unlink(actions, dist)
     self.assertEqual(2, len(actions[inst.UNLINK]))
Exemple #20
0
def solve(specs):
    return [Dist.from_string(fn) for fn in r.solve(specs)]
Exemple #21
0
 def test_adds_to_existing_actions(self):
     actions = {inst.UNLINK: [{"foo": "bar"}]}
     dist = Dist.from_string(self.generate_random_dist())
     with self.mock_platform(windows=False):
         plan.add_unlink(actions, dist)
     self.assertEqual(2, len(actions[inst.UNLINK]))
Exemple #22
0
def _ensure_dist_or_dict(fn):
    try:
        from conda.models.dist import Dist
        return Dist.from_string(fn)
    except ImportError:
        return fn
Exemple #23
0
def test_display_actions():
    os.environ["CONDA_SHOW_CHANNEL_URLS"] = "False"
    reset_context(())
    actions = defaultdict(list, {"FETCH": [Dist("sympy-0.7.2-py27_0"), Dist("numpy-1.7.1-py27_0")]})
    # The older test index doesn't have the size metadata
    index[Dist.from_string("sympy-0.7.2-py27_0.tar.bz2")]["size"] = 4374752
    index[Dist.from_string("numpy-1.7.1-py27_0.tar.bz2")]["size"] = 5994338

    with captured() as c:
        display_actions(actions, index)

    assert (
        c.stdout
        == """
The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    sympy-0.7.2                |           py27_0         4.2 MB
    numpy-1.7.1                |           py27_0         5.7 MB
    ------------------------------------------------------------
                                           Total:         9.9 MB

"""
    )

    actions = defaultdict(
        list,
        {
            "PREFIX": "/Users/aaronmeurer/anaconda/envs/test",
            "SYMLINK_CONDA": ["/Users/aaronmeurer/anaconda"],
            "LINK": ["python-3.3.2-0", "readline-6.2-0 1", "sqlite-3.7.13-0 1", "tk-8.5.13-0 1", "zlib-1.2.7-0 1"],
        },
    )

    with captured() as c:
        display_actions(actions, index)

    assert (
        c.stdout
        == """
The following NEW packages will be INSTALLED:

    python:   3.3.2-0 \n\
    readline: 6.2-0   \n\
    sqlite:   3.7.13-0
    tk:       8.5.13-0
    zlib:     1.2.7-0 \n\

"""
    )

    actions["UNLINK"] = actions["LINK"]
    actions["LINK"] = []

    with captured() as c:
        display_actions(actions, index)

    assert (
        c.stdout
        == """
The following packages will be REMOVED:

    python:   3.3.2-0 \n\
    readline: 6.2-0   \n\
    sqlite:   3.7.13-0
    tk:       8.5.13-0
    zlib:     1.2.7-0 \n\

"""
    )

    actions = defaultdict(list, {"LINK": ["cython-0.19.1-py33_0"], "UNLINK": ["cython-0.19-py33_0"]})

    with captured() as c:
        display_actions(actions, index)

    assert (
        c.stdout
        == """
The following packages will be UPDATED:

    cython: 0.19-py33_0 --> 0.19.1-py33_0

"""
    )

    actions["LINK"], actions["UNLINK"] = actions["UNLINK"], actions["LINK"]

    with captured() as c:
        display_actions(actions, index)

    assert (
        c.stdout
        == """
The following packages will be DOWNGRADED due to dependency conflicts:

    cython: 0.19.1-py33_0 --> 0.19-py33_0

"""
    )

    actions = defaultdict(
        list,
        {
            "LINK": ["cython-0.19.1-py33_0", "dateutil-1.5-py33_0", "numpy-1.7.1-py33_0"],
            "UNLINK": ["cython-0.19-py33_0", "dateutil-2.1-py33_1", "pip-1.3.1-py33_1"],
        },
    )

    with captured() as c:
        display_actions(actions, index)

    assert (
        c.stdout
        == """
The following NEW packages will be INSTALLED:

    numpy:    1.7.1-py33_0

The following packages will be REMOVED:

    pip:      1.3.1-py33_1

The following packages will be UPDATED:

    cython:   0.19-py33_0  --> 0.19.1-py33_0

The following packages will be DOWNGRADED due to dependency conflicts:

    dateutil: 2.1-py33_1   --> 1.5-py33_0   \n\

"""
    )

    actions = defaultdict(
        list,
        {
            "LINK": ["cython-0.19.1-py33_0", "dateutil-2.1-py33_1"],
            "UNLINK": ["cython-0.19-py33_0", "dateutil-1.5-py33_0"],
        },
    )

    with captured() as c:
        display_actions(actions, index)

    assert (
        c.stdout
        == """
The following packages will be UPDATED:

    cython:   0.19-py33_0 --> 0.19.1-py33_0
    dateutil: 1.5-py33_0  --> 2.1-py33_1   \n\

"""
    )

    actions["LINK"], actions["UNLINK"] = actions["UNLINK"], actions["LINK"]

    with captured() as c:
        display_actions(actions, index)

    assert (
        c.stdout
        == """
The following packages will be DOWNGRADED due to dependency conflicts:

    cython:   0.19.1-py33_0 --> 0.19-py33_0
    dateutil: 2.1-py33_1    --> 1.5-py33_0 \n\

"""
    )
Exemple #24
0
def test_display_actions():
    os.environ['CONDA_SHOW_CHANNEL_URLS'] = 'False'
    reset_context(())
    actions = defaultdict(list, {"FETCH": [Dist('sympy-0.7.2-py27_0'), Dist("numpy-1.7.1-py27_0")]})
    # The older test index doesn't have the size metadata
    d = Dist.from_string('sympy-0.7.2-py27_0.tar.bz2')
    index[d] = IndexRecord.from_objects(index[d], size=4374752)
    d = Dist.from_string("numpy-1.7.1-py27_0.tar.bz2")
    index[d] = IndexRecord.from_objects(index[d], size=5994338)

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be downloaded:

    package                    |            build
    ---------------------------|-----------------
    sympy-0.7.2                |           py27_0         4.2 MB
    numpy-1.7.1                |           py27_0         5.7 MB
    ------------------------------------------------------------
                                           Total:         9.9 MB

"""

    actions = defaultdict(list, {'PREFIX':
    '/Users/aaronmeurer/anaconda/envs/test', 'SYMLINK_CONDA':
    ['/Users/aaronmeurer/anaconda'], 'LINK': ['python-3.3.2-0', 'readline-6.2-0 1', 'sqlite-3.7.13-0 1', 'tk-8.5.13-0 1', 'zlib-1.2.7-0 1']})

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following NEW packages will be INSTALLED:

    python:   3.3.2-0 \n\
    readline: 6.2-0   \n\
    sqlite:   3.7.13-0
    tk:       8.5.13-0
    zlib:     1.2.7-0 \n\

"""

    actions['UNLINK'] = actions['LINK']
    actions['LINK'] = []

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be REMOVED:

    python:   3.3.2-0 \n\
    readline: 6.2-0   \n\
    sqlite:   3.7.13-0
    tk:       8.5.13-0
    zlib:     1.2.7-0 \n\

"""

    actions = defaultdict(list, {'LINK': ['cython-0.19.1-py33_0'], 'UNLINK':
    ['cython-0.19-py33_0']})

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be UPDATED:

    cython: 0.19-py33_0 --> 0.19.1-py33_0

"""

    actions['LINK'], actions['UNLINK'] = actions['UNLINK'], actions['LINK']

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be DOWNGRADED due to dependency conflicts:

    cython: 0.19.1-py33_0 --> 0.19-py33_0

"""

    actions = defaultdict(list, {'LINK': ['cython-0.19.1-py33_0',
        'dateutil-1.5-py33_0', 'numpy-1.7.1-py33_0'], 'UNLINK':
        ['cython-0.19-py33_0', 'dateutil-2.1-py33_1', 'pip-1.3.1-py33_1']})

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following NEW packages will be INSTALLED:

    numpy:    1.7.1-py33_0

The following packages will be REMOVED:

    pip:      1.3.1-py33_1

The following packages will be UPDATED:

    cython:   0.19-py33_0  --> 0.19.1-py33_0

The following packages will be DOWNGRADED due to dependency conflicts:

    dateutil: 2.1-py33_1   --> 1.5-py33_0   \n\

"""

    actions = defaultdict(list, {'LINK': ['cython-0.19.1-py33_0',
        'dateutil-2.1-py33_1'], 'UNLINK':  ['cython-0.19-py33_0',
            'dateutil-1.5-py33_0']})

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
The following packages will be UPDATED:

    cython:   0.19-py33_0 --> 0.19.1-py33_0
    dateutil: 1.5-py33_0  --> 2.1-py33_1   \n\

"""

    actions['LINK'], actions['UNLINK'] = actions['UNLINK'], actions['LINK']

    with captured() as c:
        display_actions(actions, index)

    assert c.stdout == """
 def ensure_dist_or_dict(fn):
     return _Dist.from_string(fn)