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
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
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
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)
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
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
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
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
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
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
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)
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
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
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)
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)
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
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
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