def test_build_env_allow_only_one_install(script): create_basic_wheel_for_package(script, 'foo', '1.0') create_basic_wheel_for_package(script, 'bar', '1.0') finder = PackageFinder([script.scratch_path], [], session=PipSession()) build_env = BuildEnvironment() for prefix in ('normal', 'overlay'): build_env.install_requirements(finder, ['foo'], prefix, 'installing foo in %s' % prefix) with pytest.raises(AssertionError): build_env.install_requirements(finder, ['bar'], prefix, 'installing bar in %s' % prefix) with pytest.raises(AssertionError): build_env.install_requirements(finder, [], prefix, 'installing in %s' % prefix)
def test_build_env_requirements_check(script): create_basic_wheel_for_package(script, 'foo', '2.0') create_basic_wheel_for_package(script, 'bar', '1.0') create_basic_wheel_for_package(script, 'bar', '3.0') create_basic_wheel_for_package(script, 'other', '0.5') script.pip_install_local('-f', script.scratch_path, 'foo', 'bar', 'other') run_with_build_env( script, ''' r = build_env.check_requirements(['foo', 'bar', 'other']) assert r == (set(), {'foo', 'bar', 'other'}), repr(r) r = build_env.check_requirements(['foo>1.0', 'bar==3.0']) assert r == (set(), {'foo>1.0', 'bar==3.0'}), repr(r) r = build_env.check_requirements(['foo>3.0', 'bar>=2.5']) assert r == (set(), {'foo>3.0', 'bar>=2.5'}), repr(r) ''') run_with_build_env( script, ''' build_env.install_requirements(finder, ['foo', 'bar==3.0'], 'normal', 'installing foo in normal') r = build_env.check_requirements(['foo', 'bar', 'other']) assert r == (set(), {'other'}), repr(r) r = build_env.check_requirements(['foo>1.0', 'bar==3.0']) assert r == (set(), set()), repr(r) r = build_env.check_requirements(['foo>3.0', 'bar>=2.5']) assert r == ({('foo==2.0', 'foo>3.0')}, set()), repr(r) ''') run_with_build_env( script, ''' build_env.install_requirements(finder, ['foo', 'bar==3.0'], 'normal', 'installing foo in normal') build_env.install_requirements(finder, ['bar==1.0'], 'overlay', 'installing foo in overlay') r = build_env.check_requirements(['foo', 'bar', 'other']) assert r == (set(), {'other'}), repr(r) r = build_env.check_requirements(['foo>1.0', 'bar==3.0']) assert r == ({('bar==1.0', 'bar==3.0')}, set()), repr(r) r = build_env.check_requirements(['foo>3.0', 'bar>=2.5']) assert r == ({('bar==1.0', 'bar>=2.5'), ('foo==2.0', 'foo>3.0')}, \ set()), repr(r) ''')
def test_build_env_overlay_prefix_has_priority(script): create_basic_wheel_for_package(script, 'pkg', '2.0') create_basic_wheel_for_package(script, 'pkg', '4.3') result = run_with_build_env( script, ''' build_env.install_requirements(finder, ['pkg==2.0'], 'overlay', 'installing pkg==2.0 in overlay') build_env.install_requirements(finder, ['pkg==4.3'], 'normal', 'installing pkg==4.3 in normal') ''', ''' from __future__ import print_function print(__import__('pkg').__version__) ''') assert result.stdout.strip() == '2.0', str(result)
def test_yaml_based(script, case): available = case.get("available", []) requests = case.get("request", []) transaction = case.get("transaction", []) assert len(requests) == len(transaction), ( "Expected requests and transaction counts to be same" ) # Create a custom index of all the packages that are supposed to be # available # XXX: This doesn't work because this isn't making an index of files. for package in available: if isinstance(package, str): package = _convert_to_dict(package) assert isinstance(package, dict), "Needs to be a dictionary" create_basic_wheel_for_package(script, **package) available_actions = { "install": handle_install_request } # use scratch path for index for request, expected in zip(requests, transaction): # The name of the key is what action has to be taken assert len(request.keys()) == 1, "Expected only one action" # Get the only key action = list(request.keys())[0] assert action in available_actions.keys(), ( "Unsupported action {!r}".format(action) ) # Perform the requested action effect = available_actions[action](script, request[action]) assert effect == expected, "Fixture did not succeed."
def test_build_env_isolation(script): # Create dummy `pkg` wheel. pkg_whl = create_basic_wheel_for_package(script, 'pkg', '1.0') # Install it to site packages. script.pip_install_local(pkg_whl) # And a copy in the user site. script.pip_install_local('--ignore-installed', '--user', pkg_whl) # And to another directory available through a .pth file. target = script.scratch_path / 'pth_install' script.pip_install_local('-t', target, pkg_whl) (script.site_packages_path / 'build_requires.pth').write( str(target) + '\n' ) # And finally to yet another directory available through PYTHONPATH. target = script.scratch_path / 'pypath_install' script.pip_install_local('-t', target, pkg_whl) script.environ["PYTHONPATH"] = target run_with_build_env( script, '', r''' from __future__ import print_function from distutils.sysconfig import get_python_lib import sys try: import pkg except ImportError: pass else: print('imported `pkg` from `%s`' % pkg.__file__, file=sys.stderr) print('system sites:\n ' + '\n '.join(sorted({ get_python_lib(plat_specific=0), get_python_lib(plat_specific=1), })), file=sys.stderr) print('sys.path:\n ' + '\n '.join(sys.path), file=sys.stderr) sys.exit(1) ''')
def test_new_resolver_presents_messages_when_backtracking_a_lot(script, N): # Generate a set of wheels that will definitely cause backtracking. for index in range(1, N+1): A_version = "{index}.0.0".format(index=index) B_version = "{index}.0.0".format(index=index) C_version = "{index_minus_one}.0.0".format(index_minus_one=index - 1) depends = ["B == " + B_version] if index != 1: depends.append("C == " + C_version) print("A", A_version, "B", B_version, "C", C_version) create_basic_wheel_for_package(script, "A", A_version, depends=depends) for index in range(1, N+1): B_version = "{index}.0.0".format(index=index) C_version = "{index}.0.0".format(index=index) depends = ["C == " + C_version] print("B", B_version, "C", C_version) create_basic_wheel_for_package(script, "B", B_version, depends=depends) for index in range(1, N+1): C_version = "{index}.0.0".format(index=index) print("C", C_version) create_basic_wheel_for_package(script, "C", C_version) # Install A result = script.pip( "install", "--no-cache-dir", "--no-index", "--find-links", script.scratch_path, "A" ) assert_installed(script, A="1.0.0", B="1.0.0", C="1.0.0") # These numbers are hard-coded in the code. if N >= 1: assert "This could take a while." in result.stdout if N >= 8: assert result.stdout.count("This could take a while.") >= 2 if N >= 13: assert "press Ctrl + C" in result.stdout
def test_new_resolver_build_directory_error_zazo_19(script): """https://github.com/pradyunsg/zazo/issues/19#issuecomment-631615674 This will first resolve like this: 1. Pin pkg-b==2.0.0 (since pkg-b has fewer choices) 2. Pin pkg-a==3.0.0 -> Conflict due to dependency pkg-b<2 3. Pin pkg-b==1.0.0 Since pkg-b is only available as sdist, both the first and third steps would trigger building from source. This ensures the preparer can build different versions of a package for the resolver. The preparer would fail with the following message if the different versions end up using the same build directory:: ERROR: pip can't proceed with requirements 'pkg-b ...' due to a pre-existing build directory (...). This is likely due to a previous installation that failed. pip is being responsible and not assuming it can delete this. Please delete it and try again. """ create_basic_wheel_for_package( script, "pkg_a", "3.0.0", depends=["pkg-b<2"], ) create_basic_wheel_for_package(script, "pkg_a", "2.0.0") create_basic_wheel_for_package(script, "pkg_a", "1.0.0") create_basic_sdist_for_package(script, "pkg_b", "2.0.0") create_basic_sdist_for_package(script, "pkg_b", "1.0.0") script.pip( "install", "--use-feature=2020-resolver", "--no-cache-dir", "--no-index", "--find-links", script.scratch_path, "pkg-a", "pkg-b", ) assert_installed(script, pkg_a="3.0.0", pkg_b="1.0.0")
def test_new_resolver_requires_python( script, requires_python, ignore_requires_python, dep_version, ): create_basic_wheel_for_package( script, "base", "0.1.0", depends=["dep"], ) create_basic_wheel_for_package( script, "dep", "0.1.0", ) create_basic_wheel_for_package( script, "dep", "0.2.0", requires_python=requires_python, ) args = [ "install", "--unstable-feature=resolver", "--no-cache-dir", "--no-index", "--find-links", script.scratch_path, ] if ignore_requires_python: args.append("--ignore-requires-python") args.append("base") script.pip(*args) assert_installed(script, base="0.1.0", dep=dep_version)
def test_new_resolver_lazy_fetch_candidates(script, upgrade): create_basic_wheel_for_package(script, "myuberpkg", "1") create_basic_wheel_for_package(script, "myuberpkg", "2") create_basic_wheel_for_package(script, "myuberpkg", "3") # Install an old version first. script.pip( "install", "--no-cache-dir", "--no-index", "--find-links", script.scratch_path, "myuberpkg==1", ) # Now install the same package again, maybe with the upgrade flag. if upgrade: pip_upgrade_args = ["--upgrade"] else: pip_upgrade_args = [] result = script.pip( "install", "--no-cache-dir", "--no-index", "--find-links", script.scratch_path, "myuberpkg", *pip_upgrade_args # Trailing comma fails on Python 2. ) # pip should install the version preferred by the strategy... if upgrade: assert_installed(script, myuberpkg="3") else: assert_installed(script, myuberpkg="1") # But should reach there in the best route possible, without trying # candidates it does not need to. assert "myuberpkg-2" not in result.stdout, str(result)
def test_new_resolver_constraint_only_marker_match(script): create_basic_wheel_for_package(script, "pkg", "1.0") create_basic_wheel_for_package(script, "pkg", "2.0") create_basic_wheel_for_package(script, "pkg", "3.0") constrants_content = textwrap.dedent( """ pkg==1.0; python_version == "{ver[0]}.{ver[1]}" # Always satisfies. pkg==2.0; python_version < "0" # Never satisfies. """ ).format(ver=sys.version_info) constraints_txt = script.scratch_path / "constraints.txt" constraints_txt.write_text(constrants_content) script.pip( "install", "--no-cache-dir", "--no-index", "-c", constraints_txt, "--find-links", script.scratch_path, "pkg", ) assert_installed(script, pkg="1.0")
def test_build_env_requirements_check(script: PipTestEnvironment) -> None: create_basic_wheel_for_package(script, "foo", "2.0") create_basic_wheel_for_package(script, "bar", "1.0") create_basic_wheel_for_package(script, "bar", "3.0") create_basic_wheel_for_package(script, "other", "0.5") script.pip_install_local("-f", script.scratch_path, "foo", "bar", "other") run_with_build_env( script, """ r = build_env.check_requirements(['foo', 'bar', 'other']) assert r == (set(), {'foo', 'bar', 'other'}), repr(r) r = build_env.check_requirements(['foo>1.0', 'bar==3.0']) assert r == (set(), {'foo>1.0', 'bar==3.0'}), repr(r) r = build_env.check_requirements(['foo>3.0', 'bar>=2.5']) assert r == (set(), {'foo>3.0', 'bar>=2.5'}), repr(r) """, ) run_with_build_env( script, """ build_env.install_requirements(finder, ['foo', 'bar==3.0'], 'normal', kind='installing foo in normal') r = build_env.check_requirements(['foo', 'bar', 'other']) assert r == (set(), {'other'}), repr(r) r = build_env.check_requirements(['foo>1.0', 'bar==3.0']) assert r == (set(), set()), repr(r) r = build_env.check_requirements(['foo>3.0', 'bar>=2.5']) assert r == ({('foo==2.0', 'foo>3.0')}, set()), repr(r) """, ) run_with_build_env( script, """ build_env.install_requirements(finder, ['foo', 'bar==3.0'], 'normal', kind='installing foo in normal') build_env.install_requirements(finder, ['bar==1.0'], 'overlay', kind='installing foo in overlay') r = build_env.check_requirements(['foo', 'bar', 'other']) assert r == (set(), {'other'}), repr(r) r = build_env.check_requirements(['foo>1.0', 'bar==3.0']) assert r == ({('bar==1.0', 'bar==3.0')}, set()), repr(r) r = build_env.check_requirements(['foo>3.0', 'bar>=2.5']) assert r == ({('bar==1.0', 'bar>=2.5'), ('foo==2.0', 'foo>3.0')}, \ set()), repr(r) """, ) run_with_build_env( script, """ build_env.install_requirements( finder, ["bar==3.0"], "normal", kind="installing bar in normal", ) r = build_env.check_requirements( [ "bar==2.0; python_version < '3.0'", "bar==3.0; python_version >= '3.0'", "foo==4.0; extra == 'dev'", ], ) assert r == (set(), set()), repr(r) """, )