Пример #1
0
def to_action(specs_to_add, specs_to_remove, prefix, to_link, to_unlink, index):
    to_link_records = []

    prefix_data = PrefixData(prefix)
    final_precs = IndexedSet(prefix_data.iter_records())

    lookup_dict = {}
    for _, c in index:
        lookup_dict[Channel(c).url(with_credentials=False)] = c

    assert len(to_unlink) == 0

    for c, pkg, jsn_s in to_link:
        sdir = lookup_dict[split_anaconda_token(remove_auth(c))[0]]
        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        final_precs.add(rec)
        to_link_records.append(rec)

    unlink_precs, link_precs = diff_for_unlink_link_precs(
        prefix,
        final_precs=IndexedSet(PrefixGraph(final_precs).graph),
        specs_to_add=specs_to_add,
    )

    actions = get_blank_actions(prefix)
    actions["UNLINK"].extend(Dist(prec) for prec in unlink_precs)
    actions["LINK"].extend(Dist(prec) for prec in link_precs)
    return actions
Пример #2
0
def test_windows_sort_orders_1():
    # This test makes sure the windows-specific parts of _toposort_prepare_graph
    # are behaving correctly.

    old_on_win = conda.models.prefix_graph.on_win
    conda.models.prefix_graph.on_win = True
    try:
        records, specs = get_windows_conda_build_record_set()
        graph = PrefixGraph(records, specs)

        nodes = tuple(rec.name for rec in graph.records)
        pprint(nodes)
        order = (
            'ca-certificates',
            'conda-env',
            'vs2015_runtime',
            'vc',
            'openssl',
            'python',
            'yaml',
            'pywin32',
            'menuinst',  # on_win, menuinst should be very early
            'affine',
            'asn1crypto',
            'beautifulsoup4',
            'certifi',
            'chardet',
            'colour',
            'cryptography-vectors',
            'filelock',
            'glob2',
            'idna',
            'markupsafe',
            'pkginfo',
            'psutil',
            'pycosat',
            'pycparser',
            'pyyaml',
            'ruamel_yaml',
            'six',
            'win_inet_pton',
            'wincertstore',
            'cffi',
            'pysocks',
            'setuptools',
            'cryptography',
            'jinja2',
            'wheel',
            'pip',  # pip always comes after python
            'pyopenssl',
            'urllib3',
            'requests',
            'conda',  # on_win, conda comes before all noarch: python packages (affine, colour, spiffy-test-app, uses-spiffy-test-app)
            'conda-build',
            'spiffy-test-app',
            'uses-spiffy-test-app',
        )
        assert nodes == order
    finally:
        conda.models.prefix_graph.on_win = old_on_win
Пример #3
0
def to_action(specs_to_add, specs_to_remove, prefix, to_link, to_unlink,
              index):
    to_link_records, to_unlink_records = [], []

    prefix_data = PrefixData(prefix)
    final_precs = IndexedSet(prefix_data.iter_records())

    lookup_dict = {}
    for _, c in index:
        lookup_dict[str(c)] = c

    for c, pkg in to_unlink:
        for i_rec in installed_pkg_recs:
            if i_rec.fn == pkg:
                final_precs.remove(i_rec)
                to_unlink_records.append(i_rec)
                break
        else:
            print("No package record found!")

    for c, pkg, jsn_s in to_link:
        sdir = lookup_dict[c]
        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        final_precs.add(rec)
        to_link_records.append(rec)

    unlink_precs, link_precs = diff_for_unlink_link_precs(
        prefix,
        final_precs=IndexedSet(PrefixGraph(final_precs).graph),
        specs_to_add=specs_to_add)

    actions = get_blank_actions(prefix)
    actions['UNLINK'].extend(Dist(prec) for prec in unlink_precs)
    actions['LINK'].extend(Dist(prec) for prec in link_precs)
    return actions
Пример #4
0
def test_windows_sort_orders_1():
    # This test makes sure the windows-specific parts of _toposort_prepare_graph
    # are behaving correctly.

    old_on_win = conda.models.prefix_graph.on_win
    conda.models.prefix_graph.on_win = True
    try:
        records, specs = get_windows_conda_build_record_set()
        graph = PrefixGraph(records, specs)

        nodes = tuple(rec.dist_str() for rec in graph.records)
        print(nodes)
        order = (
            'channel-5::ca-certificates-2017.08.26-h94faf87_0',
            'channel-5::conda-env-2.6.0-h36134e3_1',
            'channel-5::vs2015_runtime-14.0.25123-3',
            'channel-5::vc-14-h0510ff6_3',
            'channel-5::openssl-1.0.2n-h74b6da3_0',
            'channel-5::python-3.6.4-h6538335_1',
            'channel-5::yaml-0.1.7-hc54c509_2',
            'channel-5::pywin32-222-py36hfa6e2cd_0',
            'channel-5::menuinst-1.4.11-py36hfa6e2cd_0',  # on_win, menuinst should be very early
            'channel-5::asn1crypto-0.24.0-py36_0',
            'channel-5::beautifulsoup4-4.6.0-py36hd4cc5e8_1',
            'channel-5::certifi-2018.1.18-py36_0',
            'channel-5::chardet-3.0.4-py36h420ce6e_1',
            'channel-5::filelock-3.0.4-py36_0',
            'channel-5::glob2-0.6-py36hdf76b57_0',
            'channel-5::idna-2.6-py36h148d497_1',
            'channel-5::markupsafe-1.0-py36h0e26971_1',
            'channel-5::pkginfo-1.4.1-py36hb0f9cfa_1',
            'channel-5::psutil-5.4.3-py36hfa6e2cd_0',
            'channel-5::pycosat-0.6.3-py36h413d8a4_0',
            'channel-5::pycparser-2.18-py36hd053e01_1',
            'channel-5::pyyaml-3.12-py36h1d1928f_1',
            'channel-5::ruamel_yaml-0.15.35-py36hfa6e2cd_1',
            'channel-5::six-1.11.0-py36h4db2310_1',
            'channel-5::win_inet_pton-1.0.1-py36he67d7fd_1',
            'channel-5::wincertstore-0.2-py36h7fe50ca_0',
            'channel-5::cffi-1.11.4-py36hfa6e2cd_0',
            'channel-5::conda-verify-2.0.0-py36h065de53_0',
            'channel-5::pysocks-1.6.8-py36_0',
            'channel-5::setuptools-38.5.1-py36_0',
            'channel-5::cryptography-2.1.4-py36he1d7878_0',
            'channel-5::jinja2-2.10-py36h292fed1_0',
            'channel-5::wheel-0.30.0-py36h6c3ec14_1',
            'channel-5::pip-9.0.1-py36h226ae91_4',  # pip always comes after python
            'channel-5::pyopenssl-17.5.0-py36h5b7d817_0',
            'channel-5::urllib3-1.22-py36h276f60a_0',
            'channel-5::requests-2.18.4-py36h4371aae_1',
            'channel-5::conda-4.4.11-py36_0',  # on_win, conda comes before all noarch: python packages (affine, colour, spiffy-test-app, uses-spiffy-test-app)
            'channel-5::affine-2.1.0-pyh128a3a6_1',
            'channel-5::colour-0.1.4-pyhd67b51d_0',
            'channel-5::conda-build-3.5.1-py36_0',
            'channel-5::spiffy-test-app-0.5-pyh6afbcc8_0',
            'channel-5::uses-spiffy-test-app-2.0-pyh18698f2_0',
        )
        assert nodes == order
    finally:
        conda.models.prefix_graph.on_win = old_on_win
Пример #5
0
def to_txn(
    specs_to_add,
    specs_to_remove,
    prefix,
    to_link,
    to_unlink,
    installed_pkg_recs,
    index=None,
):
    if index is None:
        index = []
    to_link_records, to_unlink_records = [], []

    prefix_data = PrefixData(prefix)
    final_precs = IndexedSet(prefix_data.iter_records())

    lookup_dict = {}
    for _, c in index:
        lookup_dict[c.url(with_credentials=True)] = c

    for _, pkg in to_unlink:
        for i_rec in installed_pkg_recs:
            if i_rec.fn == pkg:
                final_precs.remove(i_rec)
                to_unlink_records.append(i_rec)
                break
        else:
            print("No package record found!")

    for c, pkg, jsn_s in to_link:
        sdir = lookup_dict[split_anaconda_token(c)[0]]
        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        final_precs.add(rec)
        to_link_records.append(rec)

    unlink_precs, link_precs = diff_for_unlink_link_precs(
        prefix,
        final_precs=IndexedSet(PrefixGraph(final_precs).graph),
        specs_to_add=specs_to_add,
        force_reinstall=context.force_reinstall,
    )

    pref_setup = PrefixSetup(
        target_prefix=prefix,
        unlink_precs=unlink_precs,
        link_precs=link_precs,
        remove_specs=specs_to_remove,
        update_specs=specs_to_add,
        neutered_specs=(),
    )

    conda_transaction = UnlinkLinkTransaction(pref_setup)
    return conda_transaction
Пример #6
0
def from_environment(name, prefix, no_builds=False, ignore_channels=False):
    """
        Get environment object from prefix
    Args:
        name: The name of environment
        prefix: The path of prefix
        no_builds: Whether has build requirement
        ignore_channels: whether ignore_channels

    Returns:     Environment object
    """
    # requested_specs_map = History(prefix).get_requested_specs_map()
    pd = PrefixData(prefix, pip_interop_enabled=True)

    precs = tuple(PrefixGraph(pd.iter_records()).graph)
    grouped_precs = groupby(lambda x: x.package_type, precs)
    conda_precs = sorted(concatv(
        grouped_precs.get(None, ()),
        grouped_precs.get(PackageType.NOARCH_GENERIC, ()),
        grouped_precs.get(PackageType.NOARCH_PYTHON, ()),
    ),
                         key=lambda x: x.name)

    pip_precs = sorted(
        concatv(
            grouped_precs.get(PackageType.VIRTUAL_PYTHON_WHEEL, ()),
            grouped_precs.get(PackageType.VIRTUAL_PYTHON_EGG_MANAGEABLE, ()),
            grouped_precs.get(PackageType.VIRTUAL_PYTHON_EGG_UNMANAGEABLE, ()),
            # grouped_precs.get(PackageType.SHADOW_PYTHON_EGG_LINK, ()),
        ),
        key=lambda x: x.name)

    if no_builds:
        dependencies = ['='.join((a.name, a.version)) for a in conda_precs]
    else:
        dependencies = [
            '='.join((a.name, a.version, a.build)) for a in conda_precs
        ]
    if pip_precs:
        dependencies.append(
            {'pip': ["%s==%s" % (a.name, a.version) for a in pip_precs]})

    channels = list(context.channels)
    if not ignore_channels:
        for prec in conda_precs:
            canonical_name = prec.channel.canonical_name
            if canonical_name not in channels:
                channels.insert(0, canonical_name)
    return Environment(name=name,
                       dependencies=dependencies,
                       channels=channels,
                       prefix=prefix)
Пример #7
0
def to_txn(specs_to_add,
           specs_to_remove,
           prefix,
           to_link,
           to_unlink,
           index=None):
    to_link_records, to_unlink_records = [], []

    prefix_data = PrefixData(prefix)
    final_precs = IndexedSet(prefix_data.iter_records())

    def get_channel(c):
        for _, chan in index:
            if str(chan) == c:
                return chan

    for c, pkg in to_unlink:
        for i_rec in installed_pkg_recs:
            if i_rec.fn == pkg:
                final_precs.remove(i_rec)
                to_unlink_records.append(i_rec)
                break
        else:
            print("No package record found!")

    for c, pkg, jsn_s in to_link:
        sdir = get_channel(c)
        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        final_precs.add(rec)
        to_link_records.append(rec)

    final_precs, specs_to_add, specs_to_remove = post_solve_handling(
        context, prefix_data, final_precs, specs_to_add, specs_to_remove)
    unlink_precs, link_precs = diff_for_unlink_link_precs(
        prefix,
        final_precs=IndexedSet(PrefixGraph(final_precs).graph),
        specs_to_add=specs_to_add,
        force_reinstall=context.force_reinstall)

    pref_setup = PrefixSetup(target_prefix=prefix,
                             unlink_precs=unlink_precs,
                             link_precs=link_precs,
                             remove_specs=specs_to_remove,
                             update_specs=specs_to_add,
                             neutered_specs=())

    conda_transaction = UnlinkLinkTransaction(pref_setup)
    return conda_transaction
Пример #8
0
def compute_final_precs(prefix_records,
                        to_link,
                        to_unlink,
                        installed_pkg_recs,
                        index=None):
    if index is None:
        index = []
    to_link_records, to_unlink_records = [], []

    final_precs = IndexedSet(prefix_records)

    lookup_dict = {}
    for _, entry in index:
        lookup_dict[entry["channel"].platform_url(
            entry["platform"], with_credentials=False)] = entry

    for _, pkg in to_unlink:
        for i_rec in installed_pkg_recs:
            if i_rec.fn == pkg:
                final_precs.remove(i_rec)
                to_unlink_records.append(i_rec)
                break
        else:
            print("No package record found!")

    for c, pkg, jsn_s in to_link:
        if c.startswith("file://"):
            # The conda functions (specifically remove_auth) assume the input
            # is a url; a file uri on windows with a drive letter messes them
            # up.
            key = c
        else:
            key = split_anaconda_token(remove_auth(c))[0]
        if key not in lookup_dict:
            raise ValueError("missing key {} in channels: {}".format(
                key, lookup_dict))
        sdir = lookup_dict[key]

        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        for ipkg in installed_pkg_recs:
            if ipkg.name == rec.name:
                rec.noarch = ipkg.noarch

        final_precs.add(rec)
        to_link_records.append(rec)

    return IndexedSet(PrefixGraph(final_precs).graph)
Пример #9
0
def post_solve_handling(context, prefix_data, final_precs, specs_to_add,
                        specs_to_remove):
    # Special case handling for various DepsModifier flags.
    if context.deps_modifier == DepsModifier.NO_DEPS:
        # In the NO_DEPS case, we need to start with the original list of packages in the
        # environment, and then only modify packages that match specs_to_add or
        # specs_to_remove.
        #
        # Help information notes that use of NO_DEPS is expected to lead to broken
        # environments.
        _no_deps_solution = IndexedSet(prefix_data.iter_records())
        only_remove_these = set(prec for spec in specs_to_remove
                                for prec in _no_deps_solution
                                if spec.match(prec))
        _no_deps_solution -= only_remove_these

        only_add_these = set(prec for spec in specs_to_add
                             for prec in final_precs if spec.match(prec))
        remove_before_adding_back = set(prec.name for prec in only_add_these)
        _no_deps_solution = IndexedSet(
            prec for prec in _no_deps_solution
            if prec.name not in remove_before_adding_back)
        _no_deps_solution |= only_add_these
        # ssc.solution_precs = _no_deps_solution
        solution_precs = _no_deps_solution

        return solution_precs, specs_to_add, specs_to_remove
    # TODO: check if solution is satisfiable, and emit warning if it's not

    elif (context.deps_modifier == DepsModifier.ONLY_DEPS
          and context.update_modifier != UpdateModifier.UPDATE_DEPS):
        # Using a special instance of PrefixGraph to remove youngest child nodes that match
        # the original specs_to_add.  It's important to remove only the *youngest* child nodes,
        # because a typical use might be `conda install --only-deps python=2 flask`, and in
        # that case we'd want to keep python.
        #
        # What are we supposed to do if flask was already in the environment?
        # We can't be removing stuff here that's already in the environment.
        #
        # What should be recorded for the user-requested specs in this case? Probably all
        # direct dependencies of flask.
        graph = PrefixGraph(final_precs, specs_to_add)
        removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
        specs_to_add = set(specs_to_add)
        specs_to_add_names = set((s.name for s in specs_to_add))

        for prec in removed_nodes:
            for dep in prec.depends:
                dep = MatchSpec(dep)
                if dep.name not in specs_to_add_names:
                    specs_to_add.add(dep)
        # unfreeze
        specs_to_add = frozenset(specs_to_add)

        # Add back packages that are already in the prefix.
        specs_to_remove_names = set(spec.name for spec in specs_to_remove)
        add_back = tuple(
            prefix_data.get(node.name, None) for node in removed_nodes
            if node.name not in specs_to_remove_names)
        solution_precs = tuple(
            PrefixGraph(concatv(graph.graph, filter(None, add_back))).graph)

        return solution_precs, specs_to_add, specs_to_remove

    return final_precs, specs_to_add, specs_to_remove
Пример #10
0
def bypass_satsolver_on_install(
    pkg_names, conda_channel="ggd-genomics", debug=False, prefix=None
):
    """Method to bypass the sat solver used by conda when a cached recipe is being installed

    bypass_satsolver_on_install
    ============================
    This method is used to run the conda install steps to install a ggd aws cahced reicpe. The
        intsallation will skip the sat solver step, ignore packages that may be additionaly installed
        or uninstalled, and performs other steps in order to install the data package without using 
        the sat solver. 
    The majority of the work is still done by conda through the use of the conda module. This method
        should only be used when a cached recipe is being installed.

    Parameters:
    -----------
    #1) pkg_name: The name of the ggd package to install. (Example: hg19-gaps)
    1) pkg_names: A list of the names of the ggd packages to install. (Example: [hg19-gaps])
    2) conda_channel: The ggd conda channel that package is being installed from. (Example: ggd-genomics)
    """

    # -------------------------------------------------------------------------
    # import statments
    # -------------------------------------------------------------------------
    from conda.base.context import context
    from conda.cli import common
    from conda.cli import install
    from conda.core.solve import Solver
    from conda.core.solve import SolverStateContainer
    from conda.common.io import Spinner
    from conda.core.link import PrefixSetup
    from conda.core.link import UnlinkLinkTransaction
    from argparse import Namespace
    from conda._vendor.boltons.setutils import IndexedSet
    from conda.models.prefix_graph import PrefixGraph
    from conda.core.solve import diff_for_unlink_link_precs
    from conda.common.compat import iteritems, itervalues, odict, text_type
    from conda._vendor.toolz import concat, concatv
    from conda.resolve import Resolve
    from conda.models.match_spec import MatchSpec
    from conda.base.constants import UpdateModifier
    from conda.common.io import ProgressBar
    from conda.gateways.logging import set_all_logger_level, set_conda_log_level
    from conda.gateways.logging import VERBOSITY_LEVELS
    from conda.gateways.logging import log
    from logging import (
        DEBUG,
        ERROR,
        Filter,
        Formatter,
        INFO,
        StreamHandler,
        WARN,
        getLogger,
    )
    import sys

    print(
        "\n:ggd:utils:bypass: Installing %s from the %s conda channel\n"
        % (", ".join(pkg_names), conda_channel)
    )

    # -------------------------------------------------------------------------
    # Nested functions
    # -------------------------------------------------------------------------
    # def bypass_sat(package_name,ssc_object): ## Package_name will be used as a key
    def bypass_sat(package_names, ssc_object):  ## Package_name will be used as a key
        """Method used to extract information during sat solving, but to bypass the sat solving step

        bypass_sat
        ==========
        This method is used to extract and process information that would have been done during the sat
        solvering step, (Solving Enviroment), bypass the sat solver, and return a filtered set of packages
        to install.

        Parameters:
        -----------
        #1) package_name: The name of the package to extract. (This is the package that will be installed)
        1) package_names: A list of package names of the packages to extract. (This is the package that will be installed)
        2) ssc_object: A processed conda SolverStateContainer object. 

        Returns:
        +++++++
        1) The updated ssc object based off the sat bypass and package filtering. 

        """

        ## From Solver.run_sat
        specs_map_set = set(itervalues(ssc_object.specs_map))

        ## Get the specs from ssc filtered by the package name
        new_odict = odict(
            [(p_name, ssc_object.specs_map[p_name]) for p_name in package_names]
        )
        final_environment_specs = IndexedSet(
            concatv(
                itervalues(new_odict),
                ssc_object.track_features_specs,
                ssc_object.pinned_specs,
            )
        )

        ## Run the resolve process and get info for desired package
        ssc_object.solution_precs = ssc_object.r.solve(tuple(final_environment_specs))

        wanted_indices = []
        for i, info in enumerate(ssc_object.solution_precs):
            for p_name in package_names:
                if p_name in ssc_object.solution_precs[i].namekey:
                    wanted_indices.append(i)

        filtered_ssc_solution_precs = [
            ssc_object.solution_precs[x] for x in wanted_indices
        ]
        ssc_object.solution_precs = filtered_ssc_solution_precs

        ## Add the final environment specs to ssc
        ssc_object.final_environment_specs = final_environment_specs

        return ssc_object

    # -------------------------------------------------------------------------
    # Run install
    # -------------------------------------------------------------------------

    ## Set the context.always_yes to True to bypass user input
    context.always_yes = True

    target_prefix = context.target_prefix if prefix == None else prefix

    # Setup solver object
    # solve = Solver(target_prefix, (conda_channel,u'default'), context.subdirs, [pkg_name])
    solve = Solver(
        target_prefix, (conda_channel, u"default"), context.subdirs, pkg_names
    )

    ## Create a solver state container
    ### Make sure to Freeze those packages already installed in the current env in order to bypass update checking.
    ssc = SolverStateContainer(
        prefix=target_prefix,
        update_modifier=UpdateModifier.FREEZE_INSTALLED,
        deps_modifier=context.deps_modifier,
        prune=True,
        ignore_pinned=context.ignore_pinned,
        force_remove=context.force_remove,
        should_retry_solve=False,
    )

    ## Get channel metadata
    with Spinner(
        "Collecting package metadata",
        not context.verbosity and not context.quiet,
        context.json,
    ):
        ssc = solve._collect_all_metadata(ssc)

    ## Set specs map to an empty map. (No need to check other specs)
    add_spec = []
    for p_name, spec in iteritems(ssc.specs_map):
        for pkg_name in pkg_names:
            if str(p_name) in pkg_name:
                add_spec.append((pkg_name, MatchSpec(pkg_name)))

    ssc.specs_map = odict(add_spec)

    ## Process the data in the solver state container
    with Spinner(
        "Processing data", not context.verbosity and not context.quiet, context.json
    ):
        ssc = solve._add_specs(ssc)
        ssc = bypass_sat(pkg_names, ssc)
        ssc = solve._post_sat_handling(ssc)

    ## create an IndexedSet from ssc.solution_precs
    ssc.solution_precs = IndexedSet(PrefixGraph(ssc.solution_precs).graph)

    ## Get linked and unlinked
    unlink_precs, link_precs = diff_for_unlink_link_precs(
        target_prefix, ssc.solution_precs, solve.specs_to_add
    )

    # set unlinked to empty indexed set so we do not unlink/remove any pacakges
    unlink_precs = IndexedSet()

    ## Create a PrefixSetup
    stp = PrefixSetup(
        solve.prefix,
        unlink_precs,
        link_precs,
        solve.specs_to_remove,
        solve.specs_to_add,
        solve.neutered_specs,
    )

    ## Create an UnlinkLinkTransaction with stp
    unlink_link_transaction = UnlinkLinkTransaction(stp)

    # create Namespace
    args = Namespace(
        channel=None,
        cmd="install",
        deps_modifier=context.deps_modifier,
        json=False,
        packages=pkg_names,
    )

    ## Set logger level
    if debug:
        WARN, INFO, DEBUG, TRACE = VERBOSITY_LEVELS
        set_all_logger_level(DEBUG)

    ## Install package
    install.handle_txn(unlink_link_transaction, solve.prefix, args, False)

    ## Retrun True if finished
    return True
Пример #11
0
def test_deep_cyclical_dependency():
    # Basically, the whole purpose of this test is to make sure nothing blows up with
    # recursion errors or anything like that.  Cyclical dependencies will always lead to
    # problems, and the tests here document the behavior.

    # "sqlite-3.20.1-haaaaaaa_4.tar.bz2": {
    #   "build": "haaaaaaa_4",
    #   "build_number": 4,
    #   "depends": [
    #     "libedit",
    #     "libgcc-ng >=7.2.0",
    #     "jinja2 2.9.6"
    #   ],
    #   "license": "Public-Domain (http://www.sqlite.org/copyright.html)",
    #   "md5": "deadbeefdd677bc3ed98ddd4deadbeef",
    #   "name": "sqlite",
    #   "sha256": "deadbeefabd915d2f13da177a29e264e59a0ae3c6fd2a31267dcc6a8deadbeef",
    #   "size": 1540584,
    #   "subdir": "linux-64",
    #   "timestamp": 1505666646842,
    #   "version": "3.20.1"
    # },
    graph = PrefixGraph(*get_sqlite_cyclical_record_set())

    nodes = tuple(rec.name for rec in graph.records)
    pprint(nodes)
    order = (
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'zlib',
        'libedit',
        'readline',
        'certifi',
        'click',
        'itsdangerous',
        'markupsafe',
        'python',
        'setuptools',
        'werkzeug',
        'jinja2',
        'flask',
        'sqlite',  # deep cyclical dependency; guess this is what we get
    )
    assert nodes == order

    # test remove spec
    # because of this deep cyclical dependency, removing jinja2 will remove sqlite and python
    expected_removal = (
        'certifi',
        'click',
        'itsdangerous',
        'markupsafe',
        'python',
        'setuptools',
        'werkzeug',
        'jinja2',
        'flask',
        'sqlite',
    )

    removed_nodes = graph.remove_spec(MatchSpec("sqlite"))
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("python"))
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("jinja2"))
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("markupsafe"))
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == expected_removal


    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    expected_removal = (
        'flask',
    )
    assert removed_nodes == expected_removal

    removed_nodes = graph.prune()
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    expected_removal = (
        'click',
        'itsdangerous',
        'werkzeug',
    )
    assert removed_nodes == expected_removal

    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    expected_removal = (
        # None, because of the cyclical dependency?
    )
    assert removed_nodes == expected_removal


    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    markupsafe_node = graph.get_node_by_name('markupsafe')
    markupsafe_ancestors = graph.all_ancestors(markupsafe_node)
    nodes = tuple(rec.name for rec in markupsafe_ancestors)
    pprint(nodes)
    order = (
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'zlib',
        'libedit',
        'readline',
        'certifi',
        'markupsafe',
        'python',
        'setuptools',
        'jinja2',
        'sqlite',
    )
    assert nodes == order

    markupsafe_descendants = graph.all_descendants(markupsafe_node)
    nodes = tuple(rec.name for rec in markupsafe_descendants)
    pprint(nodes)
    order = (
        'certifi',
        'click',
        'itsdangerous',
        'markupsafe',
        'python',
        'setuptools',
        'werkzeug',
        'jinja2',
        'flask',
        'sqlite',
    )
    assert nodes == order
Пример #12
0
def mamba_install(prefix, specs, args, env, *_, **kwargs):
    # TODO: support all various ways this happens
    # Including 'nodefaults' in the channels list disables the defaults
    channel_urls = [chan for chan in env.channels if chan != 'nodefaults']

    if 'nodefaults' not in env.channels:
        channel_urls.extend(context.channels)
    _channel_priority_map = prioritize_channels(channel_urls)

    index = get_env_index(_channel_priority_map)

    channel_json = []

    for x in index:
        # add priority here
        priority = len(_channel_priority_map) - _channel_priority_map[
            x.url_w_subdir][1]
        subpriority = 0 if x.channel.platform == 'noarch' else 1
        if os.path.exists(x.cache_path_solv):
            cache_file = x.cache_path_solv
        else:
            cache_file = x.cache_path_json
        channel_json.append(
            (str(x.channel), cache_file, priority, subpriority))

    specs = [MatchSpec(s) for s in specs]
    mamba_solve_specs = [s.conda_build_form() for s in specs]

    print("\n\nLooking for: {}\n\n".format(mamba_solve_specs))

    # TODO!
    installed_json_f = tempfile.NamedTemporaryFile('w', delete=False)
    installed_json_f.write("")  # stupid!
    installed_json_f.flush()

    solver_options = [(api.SOLVER_FLAG_ALLOW_DOWNGRADE, 1)]

    to_link, to_unlink = api.solve(channel_json, installed_json_f.name,
                                   mamba_solve_specs, solver_options,
                                   api.SOLVER_INSTALL, False, context.quiet)

    to_link_records, to_unlink_records = [], []

    final_precs = IndexedSet(PrefixData(prefix).iter_records())

    def get_channel(c):
        for x in index:
            if str(x.channel) == c:
                return x

    for c, pkg in to_unlink:
        for i_rec in installed_pkg_recs:
            if i_rec.fn == pkg:
                final_precs.remove(i_rec)
                to_unlink_records.append(i_rec)
                break
        else:
            print("No package record found!")

    for c, pkg, jsn_s in to_link:
        sdir = get_channel(c)
        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        final_precs.add(rec)
        to_link_records.append(rec)

    unlink_precs, link_precs = diff_for_unlink_link_precs(
        prefix,
        final_precs=IndexedSet(PrefixGraph(final_precs).graph),
        specs_to_add=specs,
        force_reinstall=context.force_reinstall)

    pref_setup = PrefixSetup(target_prefix=prefix,
                             unlink_precs=unlink_precs,
                             link_precs=link_precs,
                             remove_specs=[],
                             update_specs=specs)

    conda_transaction = UnlinkLinkTransaction(pref_setup)

    pfe = conda_transaction._get_pfe()
    pfe.execute()
    conda_transaction.execute()

    try:
        installed_json_f.close()
        os.unlink(installed_json_f.name)
    except:
        pass
Пример #13
0
def test_prefix_graph_1():
    # Basic initial test for public methods of PrefixGraph.

    records, specs = get_conda_build_record_set()
    graph = PrefixGraph(records, specs)

    nodes = tuple(rec.name for rec in graph.records)
    pprint(nodes)
    order = (
        'intel-openmp',
        'ca-certificates',
        'conda-env',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
        'conda-build',
    )
    assert nodes == order

    python_node = graph.get_node_by_name('python')
    python_ancestors = graph.all_ancestors(python_node)
    nodes = tuple(rec.name for rec in python_ancestors)
    pprint(nodes)
    order = (
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
    )
    assert nodes == order

    python_descendants = graph.all_descendants(python_node)
    nodes = tuple(rec.name for rec in python_descendants)
    pprint(nodes)
    order = (
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
        'conda-build',
    )
    assert nodes == order

    # test remove_specs
    removed_nodes = graph.remove_spec(MatchSpec("requests"))
    nodes = tuple(rec.name for rec in removed_nodes)
    pprint(nodes)
    order = (
        'requests',
        'conda',
        'conda-build',
    )
    assert nodes == order

    nodes = tuple(rec.name for rec in graph.records)
    pprint(nodes)
    order = (
        'conda-env',
        'intel-openmp',
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
    )
    assert nodes == order

    spec_matches = {
        'channel-4::intel-openmp-2018.0.3-0': {'intel-openmp'},
    }
    assert {node.dist_str(): set(str(ms) for ms in specs) for node, specs in graph.spec_matches.items()} == spec_matches

    removed_nodes = graph.prune()
    nodes = tuple(rec.dist_str() for rec in graph.records)
    pprint(nodes)
    order = (
        'channel-4::intel-openmp-2018.0.3-0',
    )
    assert nodes == order

    removed_nodes = tuple(rec.name for rec in removed_nodes)
    order = (
        'conda-env',
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
    )
    pprint(removed_nodes)
    assert removed_nodes == order
Пример #14
0
def test_windows_sort_orders_2():
    # This test makes sure the windows-specific parts of _toposort_prepare_graph
    # are behaving correctly.

    with env_var('CONDA_ALLOW_CYCLES', 'false', stack_callback=conda_tests_ctxt_mgmt_def_pol):
        old_on_win = conda.models.prefix_graph.on_win
        conda.models.prefix_graph.on_win = False
        try:
            records, specs = get_windows_conda_build_record_set()
            graph = PrefixGraph(records, specs)

            python_node = graph.get_node_by_name('python')
            pip_node = graph.get_node_by_name('pip')
            assert pip_node in graph.graph[python_node]
            assert python_node in graph.graph[pip_node]

            nodes = tuple(rec.name for rec in graph.records)
            pprint(nodes)
            order = (
                'ca-certificates',
                'conda-env',
                'vs2015_runtime',
                'vc',
                'openssl',
                'python',
                'yaml',
                'affine',
                'asn1crypto',
                'beautifulsoup4',
                'certifi',
                'chardet',
                'colour',
                'cryptography-vectors',
                'filelock',
                'glob2',
                'idna',
                'markupsafe',
                'pkginfo',
                'psutil',
                'pycosat',
                'pycparser',
                'pywin32',
                'pyyaml',
                'ruamel_yaml',
                'six',
                'spiffy-test-app',
                'win_inet_pton',
                'wincertstore',
                'cffi',
                'menuinst',  # not on_win, menuinst isn't changed
                'pysocks',
                'setuptools',
                'uses-spiffy-test-app',
                'cryptography',
                'jinja2',
                'wheel',
                'pip',  # pip always comes after python
                'pyopenssl',
                'urllib3',
                'requests',
                'conda',  # not on_win, no special treatment for noarch: python packages (affine, colour, spiffy-test-app, uses-spiffy-test-app)
                'conda-build',
            )
            assert nodes == order
        finally:
            conda.models.prefix_graph.on_win = old_on_win
Пример #15
0
def test_remove_youngest_descendant_nodes_with_specs():
    records, specs = get_conda_build_record_set()
    graph = PrefixGraph(records, tuple(specs) + (MatchSpec("python:requests"),))

    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()

    remaining_nodes = tuple(rec.name for rec in graph.records)
    pprint(remaining_nodes)
    order = (
        'ca-certificates',
        'conda-env',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
    )
    assert remaining_nodes == order

    order = (
        'intel-openmp',
        'conda-build',
    )
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == order

    # again
    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()

    remaining_nodes = tuple(rec.name for rec in graph.records)
    pprint(remaining_nodes)
    order = (
        'conda-env',
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
    )
    assert remaining_nodes == order

    order = (
        'conda',
    )
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == order

    # now test prune
    removed_nodes = graph.prune()

    remaining_nodes = tuple(rec.name for rec in graph.records)
    pprint(remaining_nodes)
    order = (
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'idna',
        'pycparser',
        'pysocks',
        'six',
        'cffi',
        'cryptography',
        'pyopenssl',
        'urllib3',
        'requests',
    )
    assert remaining_nodes == order

    order = (
        'conda-env',
        'patchelf',
        'yaml',
        'beautifulsoup4',
        'filelock',
        'glob2',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pyyaml',
        'ruamel_yaml',
        'setuptools',
        'jinja2',
    )
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == order
Пример #16
0
def test_prefix_graph_2():
    records, specs = get_conda_build_record_set()
    graph = PrefixGraph(records, specs)

    conda_build_node = graph.get_node_by_name('conda-build')
    del graph.spec_matches[conda_build_node]

    nodes = tuple(rec.name for rec in graph.records)
    pprint(nodes)
    order = (
        'intel-openmp',
        'ca-certificates',
        'conda-env',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
        'conda-build',
    )
    assert nodes == order

    removed_nodes = graph.prune()
    remaining_nodes = tuple(rec.name for rec in graph.records)
    pprint(remaining_nodes)
    order = (
        'intel-openmp',
        'ca-certificates',
        'conda-env',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'idna',
        'pycosat',
        'pycparser',
        'pysocks',
        'ruamel_yaml',
        'six',
        'cffi',
        'cryptography',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
    )
    assert remaining_nodes == order

    order = (
        'patchelf',
        'beautifulsoup4',
        'filelock',
        'glob2',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pyyaml',
        'setuptools',
        'jinja2',
        'conda-build',
    )
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == order
Пример #17
0
def test_prefix_graph_1():
    # Basic initial test for public methods of PrefixGraph.

    records, specs = get_conda_build_record_set()
    graph = PrefixGraph(records, specs)

    nodes = tuple(rec.dist_str() for rec in graph.records)
    print(nodes)
    order = (
        'channel-4::intel-openmp-2018.0.0-hc7b2577_8',
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::conda-env-2.6.0-h36134e3_1',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::patchelf-0.9-hf79760b_2',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::yaml-0.1.7-had09818_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::sqlite-3.22.0-h1bed415_0',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::asn1crypto-0.24.0-py36_0',
        'channel-4::beautifulsoup4-4.6.0-py36h49b8c8c_1',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::chardet-3.0.4-py36h0f667ec_1',
        'channel-4::filelock-3.0.4-py36_0',
        'channel-4::glob2-0.6-py36he249c77_0',
        'channel-4::idna-2.6-py36h82fb2a8_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::pkginfo-1.4.1-py36h215d178_1',
        'channel-4::psutil-5.4.3-py36h14c3975_0',
        'channel-4::pycosat-0.6.3-py36h0a5515d_0',
        'channel-4::pycparser-2.18-py36hf9f622e_1',
        'channel-4::pysocks-1.6.7-py36hd97a5b1_1',
        'channel-4::pyyaml-3.12-py36hafb9ca4_1',
        'channel-4::ruamel_yaml-0.15.35-py36h14c3975_1',
        'channel-4::six-1.11.0-py36h372c433_1',
        'channel-4::cffi-1.11.4-py36h9745a5d_0',
        'channel-4::conda-verify-2.0.0-py36h98955d8_0',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::cryptography-2.1.4-py36hd09be54_0',
        'channel-4::jinja2-2.10-py36ha16c418_0',
        'channel-4::pyopenssl-17.5.0-py36h20ba746_0',
        'channel-4::urllib3-1.22-py36hbe7ace6_0',
        'channel-4::requests-2.18.4-py36he2e5f8d_1',
        'channel-4::conda-4.4.10-py36_0',
        'channel-4::conda-build-3.5.1-py36_0',
    )
    assert nodes == order

    python_node = graph.get_node_by_name('python')
    python_ancestors = graph.all_ancestors(python_node)
    nodes = tuple(rec.dist_str() for rec in python_ancestors)
    print(nodes)
    order = (
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::sqlite-3.22.0-h1bed415_0',
    )
    assert nodes == order

    python_descendants = graph.all_descendants(python_node)
    nodes = tuple(rec.dist_str() for rec in python_descendants)
    print(nodes)
    order = (
        'channel-4::asn1crypto-0.24.0-py36_0',
        'channel-4::beautifulsoup4-4.6.0-py36h49b8c8c_1',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::chardet-3.0.4-py36h0f667ec_1',
        'channel-4::filelock-3.0.4-py36_0',
        'channel-4::glob2-0.6-py36he249c77_0',
        'channel-4::idna-2.6-py36h82fb2a8_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::pkginfo-1.4.1-py36h215d178_1',
        'channel-4::psutil-5.4.3-py36h14c3975_0',
        'channel-4::pycosat-0.6.3-py36h0a5515d_0',
        'channel-4::pycparser-2.18-py36hf9f622e_1',
        'channel-4::pysocks-1.6.7-py36hd97a5b1_1',
        'channel-4::pyyaml-3.12-py36hafb9ca4_1',
        'channel-4::ruamel_yaml-0.15.35-py36h14c3975_1',
        'channel-4::six-1.11.0-py36h372c433_1',
        'channel-4::cffi-1.11.4-py36h9745a5d_0',
        'channel-4::conda-verify-2.0.0-py36h98955d8_0',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::cryptography-2.1.4-py36hd09be54_0',
        'channel-4::jinja2-2.10-py36ha16c418_0',
        'channel-4::pyopenssl-17.5.0-py36h20ba746_0',
        'channel-4::urllib3-1.22-py36hbe7ace6_0',
        'channel-4::requests-2.18.4-py36he2e5f8d_1',
        'channel-4::conda-4.4.10-py36_0',
        'channel-4::conda-build-3.5.1-py36_0',
    )
    assert nodes == order

    # test remove_specs
    removed_nodes = graph.remove_spec(MatchSpec("requests"))
    nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(nodes)
    order = (
        'channel-4::requests-2.18.4-py36he2e5f8d_1',
        'channel-4::conda-4.4.10-py36_0',
        'channel-4::conda-build-3.5.1-py36_0',
    )
    assert nodes == order

    nodes = tuple(rec.dist_str() for rec in graph.records)
    print(nodes)
    order = (
        'channel-4::conda-env-2.6.0-h36134e3_1',
        'channel-4::intel-openmp-2018.0.0-hc7b2577_8',
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::patchelf-0.9-hf79760b_2',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::yaml-0.1.7-had09818_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::sqlite-3.22.0-h1bed415_0',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::asn1crypto-0.24.0-py36_0',
        'channel-4::beautifulsoup4-4.6.0-py36h49b8c8c_1',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::chardet-3.0.4-py36h0f667ec_1',
        'channel-4::filelock-3.0.4-py36_0',
        'channel-4::glob2-0.6-py36he249c77_0',
        'channel-4::idna-2.6-py36h82fb2a8_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::pkginfo-1.4.1-py36h215d178_1',
        'channel-4::psutil-5.4.3-py36h14c3975_0',
        'channel-4::pycosat-0.6.3-py36h0a5515d_0',
        'channel-4::pycparser-2.18-py36hf9f622e_1',
        'channel-4::pysocks-1.6.7-py36hd97a5b1_1',
        'channel-4::pyyaml-3.12-py36hafb9ca4_1',
        'channel-4::ruamel_yaml-0.15.35-py36h14c3975_1',
        'channel-4::six-1.11.0-py36h372c433_1',
        'channel-4::cffi-1.11.4-py36h9745a5d_0',
        'channel-4::conda-verify-2.0.0-py36h98955d8_0',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::cryptography-2.1.4-py36hd09be54_0',
        'channel-4::jinja2-2.10-py36ha16c418_0',
        'channel-4::pyopenssl-17.5.0-py36h20ba746_0',
        'channel-4::urllib3-1.22-py36hbe7ace6_0',
    )
    assert nodes == order

    spec_matches = {
        'channel-4::intel-openmp-2018.0.0-hc7b2577_8': {'intel-openmp'},
    }
    assert {node.dist_str(): set(str(ms) for ms in specs) for node, specs in graph.spec_matches.items()} == spec_matches

    removed_nodes = graph.prune()
    nodes = tuple(rec.dist_str() for rec in graph.records)
    print(nodes)
    order = (
        'channel-4::intel-openmp-2018.0.0-hc7b2577_8',
    )
    assert nodes == order

    order = (
        'channel-4::conda-env-2.6.0-h36134e3_1',
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::patchelf-0.9-hf79760b_2',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::yaml-0.1.7-had09818_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::sqlite-3.22.0-h1bed415_0',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::asn1crypto-0.24.0-py36_0',
        'channel-4::beautifulsoup4-4.6.0-py36h49b8c8c_1',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::chardet-3.0.4-py36h0f667ec_1',
        'channel-4::filelock-3.0.4-py36_0',
        'channel-4::glob2-0.6-py36he249c77_0',
        'channel-4::idna-2.6-py36h82fb2a8_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::pkginfo-1.4.1-py36h215d178_1',
        'channel-4::psutil-5.4.3-py36h14c3975_0',
        'channel-4::pycosat-0.6.3-py36h0a5515d_0',
        'channel-4::pycparser-2.18-py36hf9f622e_1',
        'channel-4::pysocks-1.6.7-py36hd97a5b1_1',
        'channel-4::pyyaml-3.12-py36hafb9ca4_1',
        'channel-4::ruamel_yaml-0.15.35-py36h14c3975_1',
        'channel-4::six-1.11.0-py36h372c433_1',
        'channel-4::cffi-1.11.4-py36h9745a5d_0',
        'channel-4::conda-verify-2.0.0-py36h98955d8_0',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::cryptography-2.1.4-py36hd09be54_0',
        'channel-4::jinja2-2.10-py36ha16c418_0',
        'channel-4::pyopenssl-17.5.0-py36h20ba746_0',
        'channel-4::urllib3-1.22-py36hbe7ace6_0',
    )
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == order
Пример #18
0
def test_prefix_graph_2():
    records, specs = get_conda_build_record_set()
    graph = PrefixGraph(records, specs)

    conda_build_node = graph.get_node_by_name('conda-build')
    del graph.spec_matches[conda_build_node]

    nodes = tuple(rec.name for rec in graph.records)
    pprint(nodes)
    order = (
        'intel-openmp',
        'ca-certificates',
        'conda-env',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
        'conda-build',
    )
    assert nodes == order

    removed_nodes = graph.prune()
    remaining_nodes = tuple(rec.name for rec in graph.records)
    pprint(remaining_nodes)
    order = (
        'intel-openmp',
        'ca-certificates',
        'conda-env',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'idna',
        'pycosat',
        'pycparser',
        'pysocks',
        'ruamel_yaml',
        'six',
        'cffi',
        'cryptography',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
    )
    assert remaining_nodes == order

    order = (
        'patchelf',
        'beautifulsoup4',
        'filelock',
        'glob2',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pyyaml',
        'setuptools',
        'jinja2',
        'conda-build',
    )
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == order
Пример #19
0
def test_windows_sort_orders_2():
    # This test makes sure the windows-specific parts of _toposort_prepare_graph
    # are behaving correctly.

    with env_var('CONDA_ALLOW_CYCLES', 'false', reset_context):
        old_on_win = conda.models.prefix_graph.on_win
        conda.models.prefix_graph.on_win = False
        try:
            records, specs = get_windows_conda_build_record_set()
            graph = PrefixGraph(records, specs)

            python_node = graph.get_node_by_name('python')
            pip_node = graph.get_node_by_name('pip')
            assert pip_node in graph.graph[python_node]
            assert python_node in graph.graph[pip_node]

            nodes = tuple(rec.dist_str() for rec in graph.records)
            print(nodes)
            order = (
                'channel-5::ca-certificates-2017.08.26-h94faf87_0',
                'channel-5::conda-env-2.6.0-h36134e3_1',
                'channel-5::vs2015_runtime-14.0.25123-3',
                'channel-5::vc-14-h0510ff6_3',
                'channel-5::openssl-1.0.2n-h74b6da3_0',
                'channel-5::python-3.6.4-h6538335_1',
                'channel-5::yaml-0.1.7-hc54c509_2',
                'channel-5::affine-2.1.0-pyh128a3a6_1',
                'channel-5::asn1crypto-0.24.0-py36_0',
                'channel-5::beautifulsoup4-4.6.0-py36hd4cc5e8_1',
                'channel-5::certifi-2018.1.18-py36_0',
                'channel-5::chardet-3.0.4-py36h420ce6e_1',
                'channel-5::colour-0.1.4-pyhd67b51d_0',
                'channel-5::filelock-3.0.4-py36_0',
                'channel-5::glob2-0.6-py36hdf76b57_0',
                'channel-5::idna-2.6-py36h148d497_1',
                'channel-5::markupsafe-1.0-py36h0e26971_1',
                'channel-5::pkginfo-1.4.1-py36hb0f9cfa_1',
                'channel-5::psutil-5.4.3-py36hfa6e2cd_0',
                'channel-5::pycosat-0.6.3-py36h413d8a4_0',
                'channel-5::pycparser-2.18-py36hd053e01_1',
                'channel-5::pywin32-222-py36hfa6e2cd_0',
                'channel-5::pyyaml-3.12-py36h1d1928f_1',
                'channel-5::ruamel_yaml-0.15.35-py36hfa6e2cd_1',
                'channel-5::six-1.11.0-py36h4db2310_1',
                'channel-5::spiffy-test-app-0.5-pyh6afbcc8_0',
                'channel-5::win_inet_pton-1.0.1-py36he67d7fd_1',
                'channel-5::wincertstore-0.2-py36h7fe50ca_0',
                'channel-5::cffi-1.11.4-py36hfa6e2cd_0',
                'channel-5::conda-verify-2.0.0-py36h065de53_0',
                'channel-5::menuinst-1.4.11-py36hfa6e2cd_0',  # not on_win, menuinst isn't changed
                'channel-5::pysocks-1.6.8-py36_0',
                'channel-5::setuptools-38.5.1-py36_0',
                'channel-5::uses-spiffy-test-app-2.0-pyh18698f2_0',
                'channel-5::cryptography-2.1.4-py36he1d7878_0',
                'channel-5::jinja2-2.10-py36h292fed1_0',
                'channel-5::wheel-0.30.0-py36h6c3ec14_1',
                'channel-5::pip-9.0.1-py36h226ae91_4',  # pip always comes after python
                'channel-5::pyopenssl-17.5.0-py36h5b7d817_0',
                'channel-5::urllib3-1.22-py36h276f60a_0',
                'channel-5::requests-2.18.4-py36h4371aae_1',
                'channel-5::conda-4.4.11-py36_0',  # not on_win, no special treatment for noarch: python packages (affine, colour, spiffy-test-app, uses-spiffy-test-app)
                'channel-5::conda-build-3.5.1-py36_0',
            )
            assert nodes == order
        finally:
            conda.models.prefix_graph.on_win = old_on_win
Пример #20
0
def mamba_install(prefix, specs, args, env, *_, **kwargs):
    # TODO: support all various ways this happens
    init_api_context()

    # Including 'nodefaults' in the channels list disables the defaults
    channel_urls = [chan for chan in env.channels if chan != 'nodefaults']

    if 'nodefaults' not in env.channels:
        channel_urls.extend(context.channels)
    _channel_priority_map = prioritize_channels(channel_urls)

    index = get_index(tuple(_channel_priority_map.keys()))

    channel_json = []

    for subdir, chan in index:
        # add priority here
        priority = len(_channel_priority_map) - _channel_priority_map[chan.url(
            with_credentials=True)][1]
        subpriority = 0 if chan.platform == 'noarch' else 1
        if subdir.loaded() == False and chan.platform != 'noarch':
            # ignore non-loaded subdir if channel is != noarch
            continue

        channel_json.append((chan, subdir.cache_path(), priority, subpriority))

    specs = [MatchSpec(s) for s in specs]
    mamba_solve_specs = [s.conda_build_form() for s in specs]

    print("\n\nLooking for: {}\n\n".format(mamba_solve_specs))

    solver_options = [(api.SOLVER_FLAG_ALLOW_DOWNGRADE, 1)]

    pool = api.Pool()
    repos = []

    for channel, cache_file, priority, subpriority in channel_json:
        repo = api.Repo(pool, str(channel), cache_file,
                        channel.url(with_credentials=True))
        repo.set_priority(priority, subpriority)
        repos.append(repo)

    solver = api.Solver(pool, solver_options)
    solver.add_jobs(mamba_solve_specs, api.SOLVER_INSTALL)
    success = solver.solve()
    if not success:
        print(solver.problems_to_str())

    package_cache = api.MultiPackageCache(context.pkgs_dirs)
    transaction = api.Transaction(solver, package_cache)
    to_link, to_unlink = transaction.to_conda()

    to_link_records, to_unlink_records = [], []

    final_precs = IndexedSet(PrefixData(prefix).iter_records())

    def get_channel(c):
        for _, chan in index:
            if str(chan) == c:
                return chan

    for c, pkg, jsn_s in to_link:
        sdir = get_channel(c)
        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        final_precs.add(rec)
        to_link_records.append(rec)

    unlink_precs, link_precs = diff_for_unlink_link_precs(
        prefix,
        final_precs=IndexedSet(PrefixGraph(final_precs).graph),
        specs_to_add=specs,
        force_reinstall=context.force_reinstall)

    pref_setup = PrefixSetup(target_prefix=prefix,
                             unlink_precs=unlink_precs,
                             link_precs=link_precs,
                             remove_specs=[],
                             update_specs=specs,
                             neutered_specs=())

    conda_transaction = UnlinkLinkTransaction(pref_setup)

    pfe = conda_transaction._get_pfe()
    pfe.execute()
    conda_transaction.execute()
Пример #21
0
def test_sort_without_prep():
    # Test the _toposort_prepare_graph method, here by not running it at all.
    # The method is invoked in every other test.  This is what happens when it's not invoked.

    with patch.object(conda.models.prefix_graph.PrefixGraph, '_toposort_prepare_graph', return_value=None):
        records, specs = get_windows_conda_build_record_set()
        graph = PrefixGraph(records, specs)

        python_node = graph.get_node_by_name('python')
        pip_node = graph.get_node_by_name('pip')
        assert pip_node in graph.graph[python_node]
        assert python_node in graph.graph[pip_node]

        nodes = tuple(rec.dist_str() for rec in graph.records)
        print(nodes)
        order = (
            'channel-5::ca-certificates-2017.08.26-h94faf87_0',
            'channel-5::conda-env-2.6.0-h36134e3_1',
            'channel-5::vs2015_runtime-14.0.25123-3',
            'channel-5::vc-14-h0510ff6_3',
            'channel-5::openssl-1.0.2n-h74b6da3_0',
            'channel-5::yaml-0.1.7-hc54c509_2',
            'channel-5::affine-2.1.0-pyh128a3a6_1',
            'channel-5::asn1crypto-0.24.0-py36_0',
            'channel-5::beautifulsoup4-4.6.0-py36hd4cc5e8_1',
            'channel-5::certifi-2018.1.18-py36_0',
            'channel-5::chardet-3.0.4-py36h420ce6e_1',
            'channel-5::colour-0.1.4-pyhd67b51d_0',
            'channel-5::filelock-3.0.4-py36_0',
            'channel-5::glob2-0.6-py36hdf76b57_0',
            'channel-5::idna-2.6-py36h148d497_1',
            'channel-5::markupsafe-1.0-py36h0e26971_1',
            'channel-5::pkginfo-1.4.1-py36hb0f9cfa_1',
            'channel-5::psutil-5.4.3-py36hfa6e2cd_0',
            'channel-5::pycosat-0.6.3-py36h413d8a4_0',
            'channel-5::pycparser-2.18-py36hd053e01_1',
            'channel-5::cffi-1.11.4-py36hfa6e2cd_0',
            'channel-5::python-3.6.4-h6538335_1',
            'channel-5::pywin32-222-py36hfa6e2cd_0',
            'channel-5::pyyaml-3.12-py36h1d1928f_1',
            'channel-5::ruamel_yaml-0.15.35-py36hfa6e2cd_1',
            'channel-5::six-1.11.0-py36h4db2310_1',
            'channel-5::spiffy-test-app-0.5-pyh6afbcc8_0',
            'channel-5::win_inet_pton-1.0.1-py36he67d7fd_1',
            'channel-5::wincertstore-0.2-py36h7fe50ca_0',
            'channel-5::conda-verify-2.0.0-py36h065de53_0',
            'channel-5::cryptography-2.1.4-py36he1d7878_0',
            'channel-5::menuinst-1.4.11-py36hfa6e2cd_0',
            'channel-5::pysocks-1.6.8-py36_0',
            'channel-5::setuptools-38.5.1-py36_0',
            'channel-5::uses-spiffy-test-app-2.0-pyh18698f2_0',
            'channel-5::jinja2-2.10-py36h292fed1_0',
            'channel-5::pyopenssl-17.5.0-py36h5b7d817_0',
            'channel-5::wheel-0.30.0-py36h6c3ec14_1',
            'channel-5::pip-9.0.1-py36h226ae91_4',
            'channel-5::urllib3-1.22-py36h276f60a_0',
            'channel-5::requests-2.18.4-py36h4371aae_1',
            'channel-5::conda-4.4.11-py36_0',
            'channel-5::conda-build-3.5.1-py36_0',
        )
        assert nodes == order

        with env_var('CONDA_ALLOW_CYCLES', 'false', reset_context):
            records, specs = get_windows_conda_build_record_set()
            with pytest.raises(CyclicalDependencyError):
                graph = PrefixGraph(records, specs)
Пример #22
0
def install(args, parser, command='install'):
    """
    mamba install, mamba update, and mamba create
    """
    context.validate_configuration()
    check_non_admin()

    newenv = bool(command == 'create')
    isupdate = bool(command == 'update')
    isinstall = bool(command == 'install')
    if newenv:
        ensure_name_or_prefix(args, command)
    prefix = context.target_prefix
    if newenv:
        check_prefix(prefix, json=context.json)
    if context.force_32bit and prefix == context.root_prefix:
        raise CondaValueError("cannot use CONDA_FORCE_32BIT=1 in base env")
    if isupdate and not (args.file or args.packages
                         or context.update_modifier == UpdateModifier.UPDATE_ALL):
        raise CondaValueError("""no package names supplied
# If you want to update to a newer version of Anaconda, type:
#
# $ conda update --prefix %s anaconda
""" % prefix)

    if not newenv:
        if isdir(prefix):
            delete_trash(prefix)
            if not isfile(join(prefix, 'conda-meta', 'history')):
                if paths_equal(prefix, context.conda_prefix):
                    raise NoBaseEnvironmentError()
                else:
                    if not path_is_clean(prefix):
                        raise DirectoryNotACondaEnvironmentError(prefix)
            else:
                # fall-through expected under normal operation
                pass
        else:
            if args.mkdir:
                try:
                    mkdir_p(prefix)
                except EnvironmentError as e:
                    raise CondaOSError("Could not create directory: %s" % prefix, caused_by=e)
            else:
                raise EnvironmentLocationNotFound(prefix)

    # context.__init__(argparse_args=args)

    prepend = not args.override_channels
    prefix = context.target_prefix

    index_args = {
        'use_cache': args.use_index_cache,
        'channel_urls': context.channels,
        'unknown': args.unknown,
        'prepend': not args.override_channels,
        'use_local': args.use_local
    }

    args_packages = [s.strip('"\'') for s in args.packages]
    if newenv and not args.no_default_packages:
        # Override defaults if they are specified at the command line
        # TODO: rework in 4.4 branch using MatchSpec
        args_packages_names = [pkg.replace(' ', '=').split('=', 1)[0] for pkg in args_packages]
        for default_pkg in context.create_default_packages:
            default_pkg_name = default_pkg.replace(' ', '=').split('=', 1)[0]
            if default_pkg_name not in args_packages_names:
                args_packages.append(default_pkg)

    num_cp = sum(s.endswith('.tar.bz2') for s in args_packages)
    if num_cp:
        if num_cp == len(args_packages):
            explicit(args_packages, prefix, verbose=not context.quiet)
            return
        else:
            raise CondaValueError("cannot mix specifications with conda package"
                                  " filenames")

    index = get_index(channel_urls=index_args['channel_urls'],
                      prepend=index_args['prepend'], platform=None,
                      use_local=index_args['use_local'], use_cache=index_args['use_cache'],
                      unknown=index_args['unknown'], prefix=prefix)

    channel_json = []
    for x in index:
        # add priority here
        if x.channel.name in index_args['channel_urls']:
            priority = len(index_args['channel_urls']) - index_args['channel_urls'].index(x.channel.name)
        else:
            priority = 0
        channel_json.append((str(x.channel), x.cache_path_json, priority))

    installed_pkg_recs, output = get_installed_packages(prefix, show_channel_urls=True)
    installed_json_f = tempfile.NamedTemporaryFile('w', delete=False)
    installed_json_f.write(json_dump(output))
    installed_json_f.flush()

    specs = []
    if args.file:
        for fpath in args.file:
            try:
                specs.extend(specs_from_url(fpath, json=context.json))
            except Unicode:
                raise CondaError("Error reading file, file should be a text file containing"
                                 " packages \nconda create --help for details")
        if '@EXPLICIT' in specs:
            explicit(specs, prefix, verbose=not context.quiet, index_args=index_args)
            return

    specs.extend(specs_from_args(args_packages, json=context.json))

    if isinstall and args.revision:
        get_revision(args.revision, json=context.json)
    elif isinstall and not (args.file or args_packages):
        raise CondaValueError("too few arguments, "
                              "must supply command line package specs or --file")

    # for 'conda update', make sure the requested specs actually exist in the prefix
    # and that they are name-only specs
    if isupdate and context.update_modifier == UpdateModifier.UPDATE_ALL:
        print("Currently, mamba can only update explicit packages! (e.g. mamba update numpy python ...)")
        exit()

    if isupdate and context.update_modifier != UpdateModifier.UPDATE_ALL:
        prefix_data = PrefixData(prefix)
        for spec in specs:
            spec = MatchSpec(spec)
            if not spec.is_name_only_spec:
                raise CondaError("Invalid spec for 'conda update': %s\n"
                                 "Use 'conda install' instead." % spec)
            if not prefix_data.get(spec.name, None):
                raise PackageNotInstalledError(prefix, spec.name)

    if newenv and args.clone:
        if args.packages:
            raise TooManyArgumentsError(0, len(args.packages), list(args.packages),
                                        'did not expect any arguments for --clone')

        clone(args.clone, prefix, json=context.json, quiet=context.quiet, index_args=index_args)
        touch_nonadmin(prefix)
        print_activate(args.name if args.name else prefix)
        return

    specs = [MatchSpec(s) for s in specs]
    mamba_solve_specs = [s.conda_build_form() for s in specs]

    print("\n\nLooking for: {}\n\n".format(mamba_solve_specs))


    strict_priority = (context.channel_priority == ChannelPriority.STRICT)
    if strict_priority:
        raise Exception("Cannot use strict priority with mamba!")

    to_link, to_unlink = api.solve(channel_json, installed_json_f.name, mamba_solve_specs, isupdate, strict_priority)

    to_link_records, to_unlink_records = [], []

    final_precs = IndexedSet(PrefixData(prefix).iter_records())

    def get_channel(c):
        for x in index:
            if str(x.channel) == c:
                return x

    for c, pkg in to_unlink:
        for i_rec in installed_pkg_recs:
            if i_rec.fn == pkg:
                final_precs.remove(i_rec)
                to_unlink_records.append(i_rec)
                break
        else:
            print("No package record found!")

    for c, pkg, jsn_s in to_link:
        sdir = get_channel(c)
        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        final_precs.add(rec)
        to_link_records.append(rec)

    unlink_precs, link_precs = diff_for_unlink_link_precs(prefix,
                                                          final_precs=IndexedSet(PrefixGraph(final_precs).graph),
                                                          specs_to_add=specs,
                                                          force_reinstall=context.force_reinstall)

    pref_setup = PrefixSetup(
        target_prefix = prefix,
        unlink_precs  = unlink_precs,
        link_precs    = link_precs,
        remove_specs  = [],
        update_specs  = specs
    )

    conda_transaction = UnlinkLinkTransaction(pref_setup)
    handle_txn(conda_transaction, prefix, args, newenv)

    try:
        installed_json_f.close()
        os.unlink(installed_json_f.name)
    except:
        pass
Пример #23
0
def test_prefix_graph_1():
    # Basic initial test for public methods of PrefixGraph.

    records, specs = get_conda_build_record_set()
    graph = PrefixGraph(records, specs)

    nodes = tuple(rec.dist_str() for rec in graph.records)
    print(nodes)
    order = (
        'channel-4::intel-openmp-2018.0.0-hc7b2577_8',
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::conda-env-2.6.0-h36134e3_1',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::patchelf-0.9-hf79760b_2',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::yaml-0.1.7-had09818_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::sqlite-3.22.0-h1bed415_0',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::asn1crypto-0.24.0-py36_0',
        'channel-4::beautifulsoup4-4.6.0-py36h49b8c8c_1',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::chardet-3.0.4-py36h0f667ec_1',
        'channel-4::filelock-3.0.4-py36_0',
        'channel-4::glob2-0.6-py36he249c77_0',
        'channel-4::idna-2.6-py36h82fb2a8_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::pkginfo-1.4.1-py36h215d178_1',
        'channel-4::psutil-5.4.3-py36h14c3975_0',
        'channel-4::pycosat-0.6.3-py36h0a5515d_0',
        'channel-4::pycparser-2.18-py36hf9f622e_1',
        'channel-4::pysocks-1.6.7-py36hd97a5b1_1',
        'channel-4::pyyaml-3.12-py36hafb9ca4_1',
        'channel-4::ruamel_yaml-0.15.35-py36h14c3975_1',
        'channel-4::six-1.11.0-py36h372c433_1',
        'channel-4::cffi-1.11.4-py36h9745a5d_0',
        'channel-4::conda-verify-2.0.0-py36h98955d8_0',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::cryptography-2.1.4-py36hd09be54_0',
        'channel-4::jinja2-2.10-py36ha16c418_0',
        'channel-4::pyopenssl-17.5.0-py36h20ba746_0',
        'channel-4::urllib3-1.22-py36hbe7ace6_0',
        'channel-4::requests-2.18.4-py36he2e5f8d_1',
        'channel-4::conda-4.4.10-py36_0',
        'channel-4::conda-build-3.5.1-py36_0',
    )
    assert nodes == order

    python_node = graph.get_node_by_name('python')
    python_ancestors = graph.all_ancestors(python_node)
    nodes = tuple(rec.dist_str() for rec in python_ancestors)
    print(nodes)
    order = (
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::sqlite-3.22.0-h1bed415_0',
    )
    assert nodes == order

    python_descendants = graph.all_descendants(python_node)
    nodes = tuple(rec.dist_str() for rec in python_descendants)
    print(nodes)
    order = (
        'channel-4::asn1crypto-0.24.0-py36_0',
        'channel-4::beautifulsoup4-4.6.0-py36h49b8c8c_1',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::chardet-3.0.4-py36h0f667ec_1',
        'channel-4::filelock-3.0.4-py36_0',
        'channel-4::glob2-0.6-py36he249c77_0',
        'channel-4::idna-2.6-py36h82fb2a8_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::pkginfo-1.4.1-py36h215d178_1',
        'channel-4::psutil-5.4.3-py36h14c3975_0',
        'channel-4::pycosat-0.6.3-py36h0a5515d_0',
        'channel-4::pycparser-2.18-py36hf9f622e_1',
        'channel-4::pysocks-1.6.7-py36hd97a5b1_1',
        'channel-4::pyyaml-3.12-py36hafb9ca4_1',
        'channel-4::ruamel_yaml-0.15.35-py36h14c3975_1',
        'channel-4::six-1.11.0-py36h372c433_1',
        'channel-4::cffi-1.11.4-py36h9745a5d_0',
        'channel-4::conda-verify-2.0.0-py36h98955d8_0',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::cryptography-2.1.4-py36hd09be54_0',
        'channel-4::jinja2-2.10-py36ha16c418_0',
        'channel-4::pyopenssl-17.5.0-py36h20ba746_0',
        'channel-4::urllib3-1.22-py36hbe7ace6_0',
        'channel-4::requests-2.18.4-py36he2e5f8d_1',
        'channel-4::conda-4.4.10-py36_0',
        'channel-4::conda-build-3.5.1-py36_0',
    )
    assert nodes == order

    # test remove_specs
    removed_nodes = graph.remove_spec(MatchSpec("requests"))
    nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(nodes)
    order = (
        'channel-4::requests-2.18.4-py36he2e5f8d_1',
        'channel-4::conda-4.4.10-py36_0',
        'channel-4::conda-build-3.5.1-py36_0',
    )
    assert nodes == order

    nodes = tuple(rec.dist_str() for rec in graph.records)
    print(nodes)
    order = (
        'channel-4::conda-env-2.6.0-h36134e3_1',
        'channel-4::intel-openmp-2018.0.0-hc7b2577_8',
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::patchelf-0.9-hf79760b_2',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::yaml-0.1.7-had09818_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::sqlite-3.22.0-h1bed415_0',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::asn1crypto-0.24.0-py36_0',
        'channel-4::beautifulsoup4-4.6.0-py36h49b8c8c_1',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::chardet-3.0.4-py36h0f667ec_1',
        'channel-4::filelock-3.0.4-py36_0',
        'channel-4::glob2-0.6-py36he249c77_0',
        'channel-4::idna-2.6-py36h82fb2a8_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::pkginfo-1.4.1-py36h215d178_1',
        'channel-4::psutil-5.4.3-py36h14c3975_0',
        'channel-4::pycosat-0.6.3-py36h0a5515d_0',
        'channel-4::pycparser-2.18-py36hf9f622e_1',
        'channel-4::pysocks-1.6.7-py36hd97a5b1_1',
        'channel-4::pyyaml-3.12-py36hafb9ca4_1',
        'channel-4::ruamel_yaml-0.15.35-py36h14c3975_1',
        'channel-4::six-1.11.0-py36h372c433_1',
        'channel-4::cffi-1.11.4-py36h9745a5d_0',
        'channel-4::conda-verify-2.0.0-py36h98955d8_0',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::cryptography-2.1.4-py36hd09be54_0',
        'channel-4::jinja2-2.10-py36ha16c418_0',
        'channel-4::pyopenssl-17.5.0-py36h20ba746_0',
        'channel-4::urllib3-1.22-py36hbe7ace6_0',
    )
    assert nodes == order

    spec_matches = {
        'channel-4::intel-openmp-2018.0.0-hc7b2577_8': {'intel-openmp'},
    }
    assert {
        node.dist_str(): set(str(ms) for ms in specs)
        for node, specs in graph.spec_matches.items()
    } == spec_matches

    removed_nodes = graph.prune()
    nodes = tuple(rec.dist_str() for rec in graph.records)
    print(nodes)
    order = ('channel-4::intel-openmp-2018.0.0-hc7b2577_8', )
    assert nodes == order

    order = (
        'channel-4::conda-env-2.6.0-h36134e3_1',
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::patchelf-0.9-hf79760b_2',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::yaml-0.1.7-had09818_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::sqlite-3.22.0-h1bed415_0',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::asn1crypto-0.24.0-py36_0',
        'channel-4::beautifulsoup4-4.6.0-py36h49b8c8c_1',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::chardet-3.0.4-py36h0f667ec_1',
        'channel-4::filelock-3.0.4-py36_0',
        'channel-4::glob2-0.6-py36he249c77_0',
        'channel-4::idna-2.6-py36h82fb2a8_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::pkginfo-1.4.1-py36h215d178_1',
        'channel-4::psutil-5.4.3-py36h14c3975_0',
        'channel-4::pycosat-0.6.3-py36h0a5515d_0',
        'channel-4::pycparser-2.18-py36hf9f622e_1',
        'channel-4::pysocks-1.6.7-py36hd97a5b1_1',
        'channel-4::pyyaml-3.12-py36hafb9ca4_1',
        'channel-4::ruamel_yaml-0.15.35-py36h14c3975_1',
        'channel-4::six-1.11.0-py36h372c433_1',
        'channel-4::cffi-1.11.4-py36h9745a5d_0',
        'channel-4::conda-verify-2.0.0-py36h98955d8_0',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::cryptography-2.1.4-py36hd09be54_0',
        'channel-4::jinja2-2.10-py36ha16c418_0',
        'channel-4::pyopenssl-17.5.0-py36h20ba746_0',
        'channel-4::urllib3-1.22-py36hbe7ace6_0',
    )
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == order
Пример #24
0
def test_deep_cyclical_dependency():
    # Basically, the whole purpose of this test is to make sure nothing blows up with
    # recursion errors or anything like that.  Cyclical dependencies will always lead to
    # problems, and the tests here document the behavior.

    # "sqlite-3.20.1-haaaaaaa_4.tar.bz2": {
    #   "build": "haaaaaaa_4",
    #   "build_number": 4,
    #   "depends": [
    #     "libedit",
    #     "libgcc-ng >=7.2.0",
    #     "jinja2 2.9.6"
    #   ],
    #   "license": "Public-Domain (http://www.sqlite.org/copyright.html)",
    #   "md5": "deadbeefdd677bc3ed98ddd4deadbeef",
    #   "name": "sqlite",
    #   "sha256": "deadbeefabd915d2f13da177a29e264e59a0ae3c6fd2a31267dcc6a8deadbeef",
    #   "size": 1540584,
    #   "subdir": "linux-64",
    #   "timestamp": 1505666646842,
    #   "version": "3.20.1"
    # },
    graph = PrefixGraph(*get_sqlite_cyclical_record_set())

    nodes = tuple(rec.dist_str() for rec in graph.records)
    print(nodes)
    order = (
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::click-6.7-py36h5253387_0',
        'channel-4::itsdangerous-0.24-py36h93cc618_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::werkzeug-0.14.1-py36_0',
        'channel-4::jinja2-2.9.6-py36h489bce4_1',
        'channel-4::flask-0.12.2-py36hb24657c_0',
        'channel-4::sqlite-3.20.1-haaaaaaa_4',  # deep cyclical dependency; guess this is what we get
    )
    assert nodes == order

    # test remove spec
    # because of this deep cyclical dependency, removing jinja2 will remove sqlite and python
    expected_removal = (
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::click-6.7-py36h5253387_0',
        'channel-4::itsdangerous-0.24-py36h93cc618_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::werkzeug-0.14.1-py36_0',
        'channel-4::jinja2-2.9.6-py36h489bce4_1',
        'channel-4::flask-0.12.2-py36hb24657c_0',
        'channel-4::sqlite-3.20.1-haaaaaaa_4',
    )

    removed_nodes = graph.remove_spec(MatchSpec("sqlite"))
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("python"))
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("jinja2"))
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("markupsafe"))
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    expected_removal = ('channel-4::flask-0.12.2-py36hb24657c_0', )
    assert removed_nodes == expected_removal

    removed_nodes = graph.prune()
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    expected_removal = (
        'channel-4::click-6.7-py36h5253387_0',
        'channel-4::itsdangerous-0.24-py36h93cc618_1',
        'channel-4::werkzeug-0.14.1-py36_0',
    )
    assert removed_nodes == expected_removal

    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    expected_removal = (
        # None, because of the cyclical dependency?
    )
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    markupsafe_node = graph.get_node_by_name('markupsafe')
    markupsafe_ancestors = graph.all_ancestors(markupsafe_node)
    nodes = tuple(rec.dist_str() for rec in markupsafe_ancestors)
    print(nodes)
    order = (
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::jinja2-2.9.6-py36h489bce4_1',
        'channel-4::sqlite-3.20.1-haaaaaaa_4',
    )
    assert nodes == order

    markupsafe_descendants = graph.all_descendants(markupsafe_node)
    nodes = tuple(rec.dist_str() for rec in markupsafe_descendants)
    print(nodes)
    order = (
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::click-6.7-py36h5253387_0',
        'channel-4::itsdangerous-0.24-py36h93cc618_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::werkzeug-0.14.1-py36_0',
        'channel-4::jinja2-2.9.6-py36h489bce4_1',
        'channel-4::flask-0.12.2-py36hb24657c_0',
        'channel-4::sqlite-3.20.1-haaaaaaa_4',
    )
    assert nodes == order
Пример #25
0
def test_windows_sort_orders_2():
    # This test makes sure the windows-specific parts of _toposort_prepare_graph
    # are behaving correctly.

    with env_var('CONDA_ALLOW_CYCLES', 'false', reset_context):
        old_on_win = conda.models.prefix_graph.on_win
        conda.models.prefix_graph.on_win = False
        try:
            records, specs = get_windows_conda_build_record_set()
            graph = PrefixGraph(records, specs)

            python_node = graph.get_node_by_name('python')
            pip_node = graph.get_node_by_name('pip')
            assert pip_node in graph.graph[python_node]
            assert python_node in graph.graph[pip_node]

            nodes = tuple(rec.name for rec in graph.records)
            pprint(nodes)
            order = (
                'ca-certificates',
                'conda-env',
                'vs2015_runtime',
                'vc',
                'openssl',
                'python',
                'yaml',
                'affine',
                'asn1crypto',
                'beautifulsoup4',
                'certifi',
                'chardet',
                'colour',
                'cryptography-vectors',
                'filelock',
                'glob2',
                'idna',
                'markupsafe',
                'pkginfo',
                'psutil',
                'pycosat',
                'pycparser',
                'pywin32',
                'pyyaml',
                'ruamel_yaml',
                'six',
                'spiffy-test-app',
                'win_inet_pton',
                'wincertstore',
                'cffi',
                'menuinst',  # not on_win, menuinst isn't changed
                'pysocks',
                'setuptools',
                'uses-spiffy-test-app',
                'cryptography',
                'jinja2',
                'wheel',
                'pip',  # pip always comes after python
                'pyopenssl',
                'urllib3',
                'requests',
                'conda',  # not on_win, no special treatment for noarch: python packages (affine, colour, spiffy-test-app, uses-spiffy-test-app)
                'conda-build',
            )
            assert nodes == order
        finally:
            conda.models.prefix_graph.on_win = old_on_win
Пример #26
0
def test_remove_youngest_descendant_nodes_with_specs():
    records, specs = get_conda_build_record_set()
    graph = PrefixGraph(records, tuple(specs) + (MatchSpec("python:requests"),))

    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()

    remaining_nodes = tuple(rec.name for rec in graph.records)
    pprint(remaining_nodes)
    order = (
        'ca-certificates',
        'conda-env',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
    )
    assert remaining_nodes == order

    order = (
        'intel-openmp',
        'conda-build',
    )
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == order

    # again
    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()

    remaining_nodes = tuple(rec.name for rec in graph.records)
    pprint(remaining_nodes)
    order = (
        'conda-env',
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
    )
    assert remaining_nodes == order

    order = (
        'conda',
    )
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == order

    # now test prune
    removed_nodes = graph.prune()

    remaining_nodes = tuple(rec.name for rec in graph.records)
    pprint(remaining_nodes)
    order = (
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'idna',
        'pycparser',
        'pysocks',
        'six',
        'cffi',
        'cryptography',
        'pyopenssl',
        'urllib3',
        'requests',
    )
    assert remaining_nodes == order

    order = (
        'conda-env',
        'patchelf',
        'yaml',
        'beautifulsoup4',
        'filelock',
        'glob2',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pyyaml',
        'ruamel_yaml',
        'setuptools',
        'jinja2',
    )
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == order
Пример #27
0
def test_sort_without_prep():
    # Test the _toposort_prepare_graph method, here by not running it at all.
    # The method is invoked in every other test.  This is what happens when it's not invoked.

    with patch.object(conda.models.prefix_graph.PrefixGraph, '_toposort_prepare_graph', return_value=None):
        records, specs = get_windows_conda_build_record_set()
        graph = PrefixGraph(records, specs)

        python_node = graph.get_node_by_name('python')
        pip_node = graph.get_node_by_name('pip')
        assert pip_node in graph.graph[python_node]
        assert python_node in graph.graph[pip_node]

        nodes = tuple(rec.name for rec in graph.records)
        pprint(nodes)
        order = (
            'ca-certificates',
            'conda-env',
            'vs2015_runtime',
            'vc',
            'openssl',
            'yaml',
            'affine',
            'asn1crypto',
            'beautifulsoup4',
            'certifi',
            'chardet',
            'colour',
            'cryptography-vectors',
            'filelock',
            'glob2',
            'idna',
            'markupsafe',
            'pkginfo',
            'psutil',
            'pycosat',
            'pycparser',
            'cffi',
            'python',
            'pywin32',
            'pyyaml',
            'ruamel_yaml',
            'six',
            'spiffy-test-app',
            'win_inet_pton',
            'wincertstore',
            'cryptography',
            'menuinst',
            'pysocks',
            'setuptools',
            'uses-spiffy-test-app',
            'jinja2',
            'pyopenssl',
            'wheel',
            'pip',
            'urllib3',
            'requests',
            'conda',
            'conda-build',
        )
        assert nodes == order

        with env_var('CONDA_ALLOW_CYCLES', 'false', reset_context):
            records, specs = get_windows_conda_build_record_set()
            with pytest.raises(CyclicalDependencyError):
                graph = PrefixGraph(records, specs)
Пример #28
0
def test_sort_without_prep():
    # Test the _toposort_prepare_graph method, here by not running it at all.
    # The method is invoked in every other test.  This is what happens when it's not invoked.

    with patch.object(conda.models.prefix_graph.PrefixGraph,
                      '_toposort_prepare_graph',
                      return_value=None):
        records, specs = get_windows_conda_build_record_set()
        graph = PrefixGraph(records, specs)

        python_node = graph.get_node_by_name('python')
        pip_node = graph.get_node_by_name('pip')
        assert pip_node in graph.graph[python_node]
        assert python_node in graph.graph[pip_node]

        nodes = tuple(rec.dist_str() for rec in graph.records)
        print(nodes)
        order = (
            'channel-5::ca-certificates-2017.08.26-h94faf87_0',
            'channel-5::conda-env-2.6.0-h36134e3_1',
            'channel-5::vs2015_runtime-14.0.25123-3',
            'channel-5::vc-14-h0510ff6_3',
            'channel-5::openssl-1.0.2n-h74b6da3_0',
            'channel-5::yaml-0.1.7-hc54c509_2',
            'channel-5::affine-2.1.0-pyh128a3a6_1',
            'channel-5::asn1crypto-0.24.0-py36_0',
            'channel-5::beautifulsoup4-4.6.0-py36hd4cc5e8_1',
            'channel-5::certifi-2018.1.18-py36_0',
            'channel-5::chardet-3.0.4-py36h420ce6e_1',
            'channel-5::colour-0.1.4-pyhd67b51d_0',
            'channel-5::filelock-3.0.4-py36_0',
            'channel-5::glob2-0.6-py36hdf76b57_0',
            'channel-5::idna-2.6-py36h148d497_1',
            'channel-5::markupsafe-1.0-py36h0e26971_1',
            'channel-5::pkginfo-1.4.1-py36hb0f9cfa_1',
            'channel-5::psutil-5.4.3-py36hfa6e2cd_0',
            'channel-5::pycosat-0.6.3-py36h413d8a4_0',
            'channel-5::pycparser-2.18-py36hd053e01_1',
            'channel-5::cffi-1.11.4-py36hfa6e2cd_0',
            'channel-5::python-3.6.4-h6538335_1',
            'channel-5::pywin32-222-py36hfa6e2cd_0',
            'channel-5::pyyaml-3.12-py36h1d1928f_1',
            'channel-5::ruamel_yaml-0.15.35-py36hfa6e2cd_1',
            'channel-5::six-1.11.0-py36h4db2310_1',
            'channel-5::spiffy-test-app-0.5-pyh6afbcc8_0',
            'channel-5::win_inet_pton-1.0.1-py36he67d7fd_1',
            'channel-5::wincertstore-0.2-py36h7fe50ca_0',
            'channel-5::conda-verify-2.0.0-py36h065de53_0',
            'channel-5::cryptography-2.1.4-py36he1d7878_0',
            'channel-5::menuinst-1.4.11-py36hfa6e2cd_0',
            'channel-5::pysocks-1.6.8-py36_0',
            'channel-5::setuptools-38.5.1-py36_0',
            'channel-5::uses-spiffy-test-app-2.0-pyh18698f2_0',
            'channel-5::jinja2-2.10-py36h292fed1_0',
            'channel-5::pyopenssl-17.5.0-py36h5b7d817_0',
            'channel-5::wheel-0.30.0-py36h6c3ec14_1',
            'channel-5::pip-9.0.1-py36h226ae91_4',
            'channel-5::urllib3-1.22-py36h276f60a_0',
            'channel-5::requests-2.18.4-py36h4371aae_1',
            'channel-5::conda-4.4.11-py36_0',
            'channel-5::conda-build-3.5.1-py36_0',
        )
        assert nodes == order

        with env_var('CONDA_ALLOW_CYCLES', 'false', reset_context):
            records, specs = get_windows_conda_build_record_set()
            with pytest.raises(CyclicalDependencyError):
                graph = PrefixGraph(records, specs)
Пример #29
0
def test_deep_cyclical_dependency():
    # Basically, the whole purpose of this test is to make sure nothing blows up with
    # recursion errors or anything like that.  Cyclical dependencies will always lead to
    # problems, and the tests here document the behavior.

    # "sqlite-3.20.1-haaaaaaa_4.tar.bz2": {
    #   "build": "haaaaaaa_4",
    #   "build_number": 4,
    #   "depends": [
    #     "libedit",
    #     "libgcc-ng >=7.2.0",
    #     "jinja2 2.9.6"
    #   ],
    #   "license": "Public-Domain (http://www.sqlite.org/copyright.html)",
    #   "md5": "deadbeefdd677bc3ed98ddd4deadbeef",
    #   "name": "sqlite",
    #   "sha256": "deadbeefabd915d2f13da177a29e264e59a0ae3c6fd2a31267dcc6a8deadbeef",
    #   "size": 1540584,
    #   "subdir": "linux-64",
    #   "timestamp": 1505666646842,
    #   "version": "3.20.1"
    # },
    graph = PrefixGraph(*get_sqlite_cyclical_record_set())

    nodes = tuple(rec.name for rec in graph.records)
    pprint(nodes)
    order = (
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'zlib',
        'libedit',
        'readline',
        'certifi',
        'click',
        'itsdangerous',
        'markupsafe',
        'python',
        'setuptools',
        'werkzeug',
        'jinja2',
        'flask',
        'sqlite',  # deep cyclical dependency; guess this is what we get
    )
    assert nodes == order

    # test remove spec
    # because of this deep cyclical dependency, removing jinja2 will remove sqlite and python
    expected_removal = (
        'certifi',
        'click',
        'itsdangerous',
        'markupsafe',
        'python',
        'setuptools',
        'werkzeug',
        'jinja2',
        'flask',
        'sqlite',
    )

    removed_nodes = graph.remove_spec(MatchSpec("sqlite"))
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("python"))
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("jinja2"))
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("markupsafe"))
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    assert removed_nodes == expected_removal


    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    expected_removal = (
        'flask',
    )
    assert removed_nodes == expected_removal

    removed_nodes = graph.prune()
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    expected_removal = (
        'click',
        'itsdangerous',
        'werkzeug',
    )
    assert removed_nodes == expected_removal

    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
    removed_nodes = tuple(rec.name for rec in removed_nodes)
    pprint(removed_nodes)
    expected_removal = (
        # None, because of the cyclical dependency?
    )
    assert removed_nodes == expected_removal


    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    markupsafe_node = graph.get_node_by_name('markupsafe')
    markupsafe_ancestors = graph.all_ancestors(markupsafe_node)
    nodes = tuple(rec.name for rec in markupsafe_ancestors)
    pprint(nodes)
    order = (
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'zlib',
        'libedit',
        'readline',
        'certifi',
        'markupsafe',
        'python',
        'setuptools',
        'jinja2',
        'sqlite',
    )
    assert nodes == order

    markupsafe_descendants = graph.all_descendants(markupsafe_node)
    nodes = tuple(rec.name for rec in markupsafe_descendants)
    pprint(nodes)
    order = (
        'certifi',
        'click',
        'itsdangerous',
        'markupsafe',
        'python',
        'setuptools',
        'werkzeug',
        'jinja2',
        'flask',
        'sqlite',
    )
    assert nodes == order
Пример #30
0
def test_sort_without_prep():
    # Test the _toposort_prepare_graph method, here by not running it at all.
    # The method is invoked in every other test.  This is what happens when it's not invoked.

    with patch.object(conda.models.prefix_graph.PrefixGraph, '_toposort_prepare_graph', return_value=None):
        records, specs = get_windows_conda_build_record_set()
        graph = PrefixGraph(records, specs)

        python_node = graph.get_node_by_name('python')
        pip_node = graph.get_node_by_name('pip')
        assert pip_node in graph.graph[python_node]
        assert python_node in graph.graph[pip_node]

        nodes = tuple(rec.name for rec in graph.records)
        pprint(nodes)
        order = (
            'ca-certificates',
            'conda-env',
            'vs2015_runtime',
            'vc',
            'openssl',
            'yaml',
            'affine',
            'asn1crypto',
            'beautifulsoup4',
            'certifi',
            'chardet',
            'colour',
            'cryptography-vectors',
            'filelock',
            'glob2',
            'idna',
            'markupsafe',
            'pkginfo',
            'psutil',
            'pycosat',
            'pycparser',
            'cffi',
            'python',
            'pywin32',
            'pyyaml',
            'ruamel_yaml',
            'six',
            'spiffy-test-app',
            'win_inet_pton',
            'wincertstore',
            'cryptography',
            'menuinst',
            'pysocks',
            'setuptools',
            'uses-spiffy-test-app',
            'jinja2',
            'pyopenssl',
            'wheel',
            'pip',
            'urllib3',
            'requests',
            'conda',
            'conda-build',
        )
        assert nodes == order

        with env_var('CONDA_ALLOW_CYCLES', 'false', stack_callback=conda_tests_ctxt_mgmt_def_pol):
            records, specs = get_windows_conda_build_record_set()
            with pytest.raises(CyclicalDependencyError):
                graph = PrefixGraph(records, specs)
Пример #31
0
def to_txn(
    specs_to_add,
    specs_to_remove,
    prefix,
    to_link,
    to_unlink,
    installed_pkg_recs,
    index=None,
):
    if index is None:
        index = []
    to_link_records, to_unlink_records = [], []

    prefix_data = PrefixData(prefix)
    final_precs = IndexedSet(prefix_data.iter_records())

    lookup_dict = {}
    for _, entry in index:
        lookup_dict[entry["channel"].platform_url(
            entry["platform"], with_credentials=False)] = entry

    for _, pkg in to_unlink:
        for i_rec in installed_pkg_recs:
            if i_rec.fn == pkg:
                final_precs.remove(i_rec)
                to_unlink_records.append(i_rec)
                break
        else:
            print("No package record found!")

    for c, pkg, jsn_s in to_link:
        if c.startswith("file://"):
            # The conda functions (specifically remove_auth) assume the input
            # is a url; a file uri on windows with a drive letter messes them
            # up.
            key = c
        else:
            key = split_anaconda_token(remove_auth(c))[0]
        if key not in lookup_dict:
            raise ValueError("missing key {} in channels: {}".format(
                key, lookup_dict))
        sdir = lookup_dict[key]
        rec = to_package_record_from_subjson(sdir, pkg, jsn_s)
        final_precs.add(rec)
        to_link_records.append(rec)

    unlink_precs, link_precs = diff_for_unlink_link_precs(
        prefix,
        final_precs=IndexedSet(PrefixGraph(final_precs).graph),
        specs_to_add=specs_to_add,
        force_reinstall=context.force_reinstall,
    )

    pref_setup = PrefixSetup(
        target_prefix=prefix,
        unlink_precs=unlink_precs,
        link_precs=link_precs,
        remove_specs=specs_to_remove,
        update_specs=specs_to_add,
        neutered_specs=(),
    )

    conda_transaction = UnlinkLinkTransaction(pref_setup)
    return conda_transaction
Пример #32
0
def test_prefix_graph_1():
    # Basic initial test for public methods of PrefixGraph.

    records, specs = get_conda_build_record_set()
    graph = PrefixGraph(records, specs)

    nodes = tuple(rec.name for rec in graph.records)
    pprint(nodes)
    order = (
        'intel-openmp',
        'ca-certificates',
        'conda-env',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
        'conda-build',
    )
    assert nodes == order

    python_node = graph.get_node_by_name('python')
    python_ancestors = graph.all_ancestors(python_node)
    nodes = tuple(rec.name for rec in python_ancestors)
    pprint(nodes)
    order = (
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'tk',
        'xz',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
    )
    assert nodes == order

    python_descendants = graph.all_descendants(python_node)
    nodes = tuple(rec.name for rec in python_descendants)
    pprint(nodes)
    order = (
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
        'requests',
        'conda',
        'conda-build',
    )
    assert nodes == order

    # test remove_specs
    removed_nodes = graph.remove_spec(MatchSpec("requests"))
    nodes = tuple(rec.name for rec in removed_nodes)
    pprint(nodes)
    order = (
        'requests',
        'conda',
        'conda-build',
    )
    assert nodes == order

    nodes = tuple(rec.name for rec in graph.records)
    pprint(nodes)
    order = (
        'conda-env',
        'intel-openmp',
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
    )
    assert nodes == order

    spec_matches = {
        'channel-4::intel-openmp-2018.0.3-0': {'intel-openmp'},
    }
    assert {node.dist_str(): set(str(ms) for ms in specs) for node, specs in graph.spec_matches.items()} == spec_matches

    removed_nodes = graph.prune()
    nodes = tuple(rec.dist_str() for rec in graph.records)
    pprint(nodes)
    order = (
        'channel-4::intel-openmp-2018.0.3-0',
    )
    assert nodes == order

    removed_nodes = tuple(rec.name for rec in removed_nodes)
    order = (
        'conda-env',
        'ca-certificates',
        'libgcc-ng',
        'libstdcxx-ng',
        'libffi',
        'ncurses',
        'openssl',
        'patchelf',
        'tk',
        'xz',
        'yaml',
        'zlib',
        'libedit',
        'readline',
        'sqlite',
        'python',
        'asn1crypto',
        'beautifulsoup4',
        'certifi',
        'chardet',
        'cryptography-vectors',
        'filelock',
        'glob2',
        'idna',
        'markupsafe',
        'pkginfo',
        'psutil',
        'pycosat',
        'pycparser',
        'pysocks',
        'pyyaml',
        'ruamel_yaml',
        'six',
        'cffi',
        'setuptools',
        'cryptography',
        'jinja2',
        'pyopenssl',
        'urllib3',
    )
    pprint(removed_nodes)
    assert removed_nodes == order
Пример #33
0
def test_deep_cyclical_dependency():
    # Basically, the whole purpose of this test is to make sure nothing blows up with
    # recursion errors or anything like that.  Cyclical dependencies will always lead to
    # problems, and the tests here document the behavior.

    # "sqlite-3.20.1-haaaaaaa_4.tar.bz2": {
    #   "build": "haaaaaaa_4",
    #   "build_number": 4,
    #   "depends": [
    #     "libedit",
    #     "libgcc-ng >=7.2.0",
    #     "jinja2 2.9.6"
    #   ],
    #   "license": "Public-Domain (http://www.sqlite.org/copyright.html)",
    #   "md5": "deadbeefdd677bc3ed98ddd4deadbeef",
    #   "name": "sqlite",
    #   "sha256": "deadbeefabd915d2f13da177a29e264e59a0ae3c6fd2a31267dcc6a8deadbeef",
    #   "size": 1540584,
    #   "subdir": "linux-64",
    #   "timestamp": 1505666646842,
    #   "version": "3.20.1"
    # },
    graph = PrefixGraph(*get_sqlite_cyclical_record_set())

    nodes = tuple(rec.dist_str() for rec in graph.records)
    print(nodes)
    order = (
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::click-6.7-py36h5253387_0',
        'channel-4::itsdangerous-0.24-py36h93cc618_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::werkzeug-0.14.1-py36_0',
        'channel-4::jinja2-2.9.6-py36h489bce4_1',
        'channel-4::flask-0.12.2-py36hb24657c_0',
        'channel-4::sqlite-3.20.1-haaaaaaa_4',  # deep cyclical dependency; guess this is what we get
    )
    assert nodes == order

    # test remove spec
    # because of this deep cyclical dependency, removing jinja2 will remove sqlite and python
    expected_removal = (
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::click-6.7-py36h5253387_0',
        'channel-4::itsdangerous-0.24-py36h93cc618_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::werkzeug-0.14.1-py36_0',
        'channel-4::jinja2-2.9.6-py36h489bce4_1',
        'channel-4::flask-0.12.2-py36hb24657c_0',
        'channel-4::sqlite-3.20.1-haaaaaaa_4',
    )

    removed_nodes = graph.remove_spec(MatchSpec("sqlite"))
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("python"))
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("jinja2"))
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == expected_removal

    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_spec(MatchSpec("markupsafe"))
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    assert removed_nodes == expected_removal


    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    expected_removal = (
        'channel-4::flask-0.12.2-py36hb24657c_0',
    )
    assert removed_nodes == expected_removal

    removed_nodes = graph.prune()
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    expected_removal = (
        'channel-4::click-6.7-py36h5253387_0',
        'channel-4::itsdangerous-0.24-py36h93cc618_1',
        'channel-4::werkzeug-0.14.1-py36_0',
    )
    assert removed_nodes == expected_removal

    removed_nodes = graph.remove_youngest_descendant_nodes_with_specs()
    removed_nodes = tuple(rec.dist_str() for rec in removed_nodes)
    print(removed_nodes)
    expected_removal = (
        # None, because of the cyclical dependency?
    )
    assert removed_nodes == expected_removal


    graph = PrefixGraph(*get_sqlite_cyclical_record_set())
    markupsafe_node = graph.get_node_by_name('markupsafe')
    markupsafe_ancestors = graph.all_ancestors(markupsafe_node)
    nodes = tuple(rec.dist_str() for rec in markupsafe_ancestors)
    print(nodes)
    order = (
        'channel-4::ca-certificates-2017.08.26-h1d4fec5_0',
        'channel-4::libgcc-ng-7.2.0-h7cc24e2_2',
        'channel-4::libstdcxx-ng-7.2.0-h7a57d05_2',
        'channel-4::libffi-3.2.1-hd88cf55_4',
        'channel-4::ncurses-6.0-h9df7e31_2',
        'channel-4::openssl-1.0.2n-hb7f436b_0',
        'channel-4::tk-8.6.7-hc745277_3',
        'channel-4::xz-5.2.3-h55aa19d_2',
        'channel-4::zlib-1.2.11-ha838bed_2',
        'channel-4::libedit-3.1-heed3624_0',
        'channel-4::readline-7.0-ha6073c6_4',
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::jinja2-2.9.6-py36h489bce4_1',
        'channel-4::sqlite-3.20.1-haaaaaaa_4',
    )
    assert nodes == order

    markupsafe_descendants = graph.all_descendants(markupsafe_node)
    nodes = tuple(rec.dist_str() for rec in markupsafe_descendants)
    print(nodes)
    order = (
        'channel-4::certifi-2018.1.18-py36_0',
        'channel-4::click-6.7-py36h5253387_0',
        'channel-4::itsdangerous-0.24-py36h93cc618_1',
        'channel-4::markupsafe-1.0-py36hd9260cd_1',
        'channel-4::python-3.6.4-hc3d631a_1',
        'channel-4::setuptools-38.5.1-py36_0',
        'channel-4::werkzeug-0.14.1-py36_0',
        'channel-4::jinja2-2.9.6-py36h489bce4_1',
        'channel-4::flask-0.12.2-py36hb24657c_0',
        'channel-4::sqlite-3.20.1-haaaaaaa_4',
    )
    assert nodes == order