def pip_package_versions(index, package): format_control = FormatControl(no_binary=(':all:',), only_binary=()) session = PipSession() finder = PackageFinder([], [index], format_control=format_control, session=session, trusted_hosts=[urlparse(index).netloc.rsplit(':', 1)[0]]) return sorted((PipPackage(str(pv.version), pv.location) for pv in finder.find_all_candidates(package)), key=lambda pp: (pp.version, {'.tar.gz': 1, '.zip': 2, '.tar.bz2': 3}.get(pp.link.ext, 10000)))
def test_sort_locations_non_existing_path(): """ Test that a non-existing path is ignored. """ finder = PackageFinder([], [], session=PipSession()) files, urls = finder._sort_locations( [os.path.join('this', 'doesnt', 'exist')]) assert not urls and not files, "nothing should have been found"
def test_sort_locations_file_not_find_link(data): """ Test that a file:// url dir that's not a find-link, doesn't get a listdir run """ finder = PackageFinder([], [], session=PipSession()) files, urls = finder._sort_locations([data.index_url("empty_with_pkg")]) assert urls and not files, "urls, but not files should have been found"
def test_sort_locations_file_expand_dir(data): """ Test that a file:// dir gets listdir run with expand_dir """ finder = PackageFinder([data.find_links], [], session=PipSession()) files, urls = finder._sort_locations([data.find_links], expand_dir=True) assert files and not urls, ( "files and not urls should have been found at find-links url: %s" % data.find_links )
class TestLinkPackageVersions(object): # patch this for travis which has distribute in its base env for now @patch( 'pip._internal.wheel.pkg_resources.get_distribution', lambda x: Distribution(project_name='setuptools', version='0.9') ) def setup(self): self.version = '1.0' self.search_name = 'pytest' self.canonical_name = 'pytest' self.finder = PackageFinder( [], [], session=PipSession(), ) @pytest.mark.parametrize( 'url', [ 'http:/yo/pytest-1.0.tar.gz', 'http:/yo/pytest-1.0-py2.py3-none-any.whl', ], ) def test_link_package_versions_match(self, url): """Test that 'pytest' archives match for 'pytest'""" link = Link(url) search = Search( supplied=self.search_name, canonical=self.canonical_name, formats=['source', 'binary'], ) result = self.finder._link_package_versions(link, search) expected = InstallationCandidate(self.search_name, self.version, link) assert result == expected, result @pytest.mark.parametrize( 'url', [ # TODO: Uncomment this test case when #1217 is fixed. # 'http:/yo/pytest-xdist-1.0.tar.gz', 'http:/yo/pytest2-1.0.tar.gz', 'http:/yo/pytest_xdist-1.0-py2.py3-none-any.whl', ], ) def est_link_package_versions_substring_fails(self, url): """Test that 'pytest<something> archives won't match for 'pytest'.""" link = Link(url) search = Search( supplied=self.search_name, canonical=self.canonical_name, formats=['source', 'binary'], ) result = self.finder._link_package_versions(link, search) assert result is None, result
def test_get_formatted_locations_basic_auth(): """ Test that basic authentication credentials defined in URL is not included in formatted output. """ index_urls = [ 'https://pypi.org/simple', 'https://*****:*****@repo.domain.com', ] finder = PackageFinder([], index_urls, session=[]) result = finder.get_formatted_locations() assert 'user' not in result and 'pass' not in result
def setup(self): self.version = '1.0' self.parsed_version = parse_version(self.version) self.search_name = 'pytest' self.finder = PackageFinder( [], [], session=PipSession(), )
def test_skip_invalid_wheel_link(self, caplog, data): """ Test if PackageFinder skips invalid wheel filenames """ req = InstallRequirement.from_line("invalid") # data.find_links contains "invalid.whl", which is an invalid wheel finder = PackageFinder( [data.find_links], [], session=PipSession(), ) with pytest.raises(DistributionNotFound): finder.find_requirement(req, True) assert ( "invalid.whl; invalid wheel filename" in caplog.text )
def setup(self): self.version = '1.0' self.search_name = 'pytest' self.canonical_name = 'pytest' self.finder = PackageFinder( [], [], session=PipSession(), )
def test_finder_priority_page_over_deplink(): """ Test PackageFinder prefers page links over equivalent dependency links """ req = InstallRequirement.from_line('pip==1.5.6', None) finder = PackageFinder( [], ["https://pypi.python.org/simple"], process_dependency_links=True, session=PipSession(), ) finder.add_dependency_links([ 'https://warehouse.python.org/packages/source/p/pip/pip-1.5.6.tar.gz']) all_versions = finder.find_all_candidates(req.name) # Check that the dependency_link is last assert all_versions[-1].location.url.startswith('https://warehouse') link = finder.find_requirement(req, False) assert link.url.startswith("https://pypi"), link
class test_link_package_versions(object): # patch this for travis which has distribute in its base env for now @patch( 'pip._internal.wheel.pkg_resources.get_distribution', lambda x: Distribution(project_name='setuptools', version='0.9') ) def setup(self): self.version = '1.0' self.parsed_version = parse_version(self.version) self.search_name = 'pytest' self.finder = PackageFinder( [], [], session=PipSession(), ) def test_link_package_versions_match_wheel(self): """Test that 'pytest' archives match for 'pytest'""" # TODO: Uncomment these, when #1217 is fixed # link = Link('http:/yo/pytest-1.0.tar.gz') # result = self.finder._link_package_versions(link, self.search_name) # assert result == [(self.parsed_version, link, self.version)], result link = Link('http:/yo/pytest-1.0-py2.py3-none-any.whl') result = self.finder._link_package_versions(link, self.search_name) assert result == [(self.parsed_version, link, self.version)], result def test_link_package_versions_substring_fails(self): """Test that 'pytest<something> archives won't match for 'pytest'""" # TODO: Uncomment these, when #1217 is fixed # link = Link('http:/yo/pytest-xdist-1.0.tar.gz') # result = self.finder._link_package_versions(link, self.search_name) # assert result == [], result # link = Link('http:/yo/pytest2-1.0.tar.gz') # result = self.finder._link_package_versions(link, self.search_name) # assert result == [], result link = Link('http:/yo/pytest_xdist-1.0-py2.py3-none-any.whl') result = self.finder._link_package_versions(link, self.search_name) assert result == [], result
def test_finder_detects_latest_already_satisfied_pypi_links(): """Test PackageFinder detects latest already satisfied using pypi links""" req = InstallRequirement.from_line('initools', None) # the latest initools on pypi is 0.3.1 latest_version = "0.3.1" satisfied_by = Mock( location="/path", parsed_version=parse_version(latest_version), version=latest_version, ) req.satisfied_by = satisfied_by finder = PackageFinder( [], ["http://pypi.python.org/simple"], session=PipSession(), ) with pytest.raises(BestVersionAlreadyInstalled): finder.find_requirement(req, True)
def test_finder_installs_pre_releases_with_version_spec(): """ Test PackageFinder only accepts stable versioned releases by default. """ req = InstallRequirement.from_line("bar>=0.0.dev0", None) links = ["https://foo/bar-1.0.tar.gz", "https://foo/bar-2.0b1.tar.gz"] finder = PackageFinder(links, [], session=PipSession()) with patch.object(finder, "_get_pages", lambda x, y: []): link = finder.find_requirement(req, False) assert link.url == "https://foo/bar-2.0b1.tar.gz" links.reverse() finder = PackageFinder(links, [], session=PipSession()) with patch.object(finder, "_get_pages", lambda x, y: []): link = finder.find_requirement(req, False) assert link.url == "https://foo/bar-2.0b1.tar.gz"
def test_find_wheel_supported(self, data, monkeypatch): """ Test finding supported wheel. """ monkeypatch.setattr( pip._internal.pep425tags, "get_supported", lambda **kw: [('py2', 'none', 'any')], ) req = InstallRequirement.from_line("simple.dist") finder = PackageFinder( [data.find_links], [], session=PipSession(), ) found = finder.find_requirement(req, True) assert ( found.url.endswith("simple.dist-0.1-py2.py3-none-any.whl") ), found
def test_not_find_wheel_not_supported(self, data, monkeypatch): """ Test not finding an unsupported wheel. """ monkeypatch.setattr( pip._internal.pep425tags, "get_supported", lambda **kw: [("py1", "none", "any")], ) req = InstallRequirement.from_line("simple.dist") finder = PackageFinder( [data.find_links], [], session=PipSession(), ) finder.valid_tags = pip._internal.pep425tags.get_supported() with pytest.raises(DistributionNotFound): finder.find_requirement(req, True)
def test_existing_over_wheel_priority(self, data): """ Test existing install has priority over wheels. `test_link_sorting` also covers this at a lower level """ req = InstallRequirement.from_line('priority', None) latest_version = "1.0" satisfied_by = Mock( location="/path", parsed_version=parse_version(latest_version), version=latest_version, ) req.satisfied_by = satisfied_by finder = PackageFinder( [data.find_links], [], session=PipSession(), ) with pytest.raises(BestVersionAlreadyInstalled): finder.find_requirement(req, True)
def test_link_sorting(self): """ Test link sorting """ links = [ InstallationCandidate("simple", "2.0", Link('simple-2.0.tar.gz')), InstallationCandidate( "simple", "1.0", Link('simple-1.0-pyT-none-TEST.whl'), ), InstallationCandidate( "simple", '1.0', Link('simple-1.0-pyT-TEST-any.whl'), ), InstallationCandidate( "simple", '1.0', Link('simple-1.0-pyT-none-any.whl'), ), InstallationCandidate( "simple", '1.0', Link('simple-1.0.tar.gz'), ), ] finder = PackageFinder([], [], session=PipSession()) finder.valid_tags = [ ('pyT', 'none', 'TEST'), ('pyT', 'TEST', 'any'), ('pyT', 'none', 'any'), ] results = sorted(links, key=finder._candidate_sort_key, reverse=True) results2 = sorted(reversed(links), key=finder._candidate_sort_key, reverse=True) assert links == results == results2, results2
def test_finder_only_installs_data_require(data): """ Test whether the PackageFinder understand data-python-requires This can optionally be exposed by a simple-repository to tell which distribution are compatible with which version of Python by adding a data-python-require to the anchor links. See pep 503 for more informations. """ # using a local index (that has pre & dev releases) finder = PackageFinder([], [data.index_url("datarequire")], session=PipSession()) links = finder.find_all_candidates("fakepackage") expected = ['1.0.0', '9.9.9'] if (2, 7) < sys.version_info < (3,): expected.append('2.7.0') elif sys.version_info > (3, 3): expected.append('3.3.0') assert {str(v.version) for v in links} == set(expected)
def test_iter_secure_origins__none_trusted_hosts(self): """ Test iter_secure_origins() after passing trusted_hosts=None. """ # Use PackageFinder.create() rather than make_test_finder() # to make sure we're really passing trusted_hosts=None. search_scope = SearchScope([], []) finder = PackageFinder.create( search_scope=search_scope, allow_yanked=True, trusted_hosts=None, session=object(), ) actual = list(finder.iter_secure_origins()) assert len(actual) == 6 # Spot-check that SECURE_ORIGINS is included. assert actual[0] == ('https', '*', '*')
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.create( [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_missing_hash_with_require_hashes_in_reqs_file(self, data, tmpdir): """--require-hashes in a requirements file should make its way to the RequirementSet. """ req_set = RequirementSet(require_hashes=False) session = PipSession() finder = PackageFinder([data.find_links], [], session=session) command = InstallCommand() with requirements_file('--require-hashes', tmpdir) as reqs_file: options, args = command.parse_args(['-r', reqs_file]) command.populate_requirement_set(req_set, args, options, finder, session, command.name, wheel_cache=None) assert req_set.require_hashes
def test_no_reuse_existing_build_dir(self, data): """Test prepare_files raise exception with previous build dir""" build_dir = os.path.join(self.tempdir, 'build', 'simple') os.makedirs(build_dir) open(os.path.join(build_dir, "setup.py"), 'w') reqset = RequirementSet() req = InstallRequirement.from_line('simple') reqset.add_requirement(req) finder = PackageFinder([data.find_links], [], session=PipSession()) resolver = self._basic_resolver(finder) assert_raises_regexp( PreviousBuildDirError, r"pip can't proceed with [\s\S]*%s[\s\S]*%s" % (req, build_dir.replace('\\', '\\\\')), resolver.resolve, reqset, )
def test_create__format_control(self): """ Test that the format_control attribute is set correctly. """ format_control = FormatControl(set(), {':all:'}) selection_prefs = SelectionPreferences( allow_yanked=True, format_control=format_control, ) finder = PackageFinder.create( search_scope=SearchScope([], []), selection_prefs=selection_prefs, session=PipSession(), ) actual_format_control = finder.format_control assert actual_format_control is format_control # Check that the attributes weren't reset. assert actual_format_control.only_binary == {':all:'}
def test_environment_marker_extras(self, data): """ Test that the environment marker extras are used with non-wheel installs. """ reqset = RequirementSet() req = install_req_from_editable( data.packages.join("LocalEnvironMarker")) req.is_direct = True reqset.add_requirement(req) finder = PackageFinder([data.find_links], [], session=PipSession()) resolver = self._basic_resolver(finder) resolver.resolve(reqset) # This is hacky but does test both case in py2 and py3 if sys.version_info[:2] in ((2, 7), (3, 4)): assert reqset.has_requirement('simple') else: assert not reqset.has_requirement('simple')
def _build_package_finder(self, options, session): """ Create a package finder appropriate to this list command. """ search_scope = make_search_scope(options) # Pass allow_yanked=False to ignore yanked versions. selection_prefs = SelectionPreferences( allow_yanked=False, allow_all_prereleases=options.pre, ) return PackageFinder.create( search_scope=search_scope, selection_prefs=selection_prefs, trusted_hosts=options.trusted_hosts, session=session, )
def test_unhashed_deps_on_require_hashes(self, data): """Make sure unhashed, unpinned, or otherwise unrepeatable dependencies get complained about when --require-hashes is on.""" reqset = RequirementSet() finder = PackageFinder([data.find_links], [], session=PipSession()) resolver = self._basic_resolver(finder) reqset.add_requirement( next( process_line( 'TopoRequires2==0.0.1 ' # requires TopoRequires '--hash=sha256:eaf9a01242c9f2f42cf2bd82a6a848cd' 'e3591d14f7896bdbefcf48543720c970', 'file', 1))) assert_raises_regexp( HashErrors, r'In --require-hashes mode, all requirements must have their ' r'versions pinned.*\n' r' TopoRequires from .*$', resolver.resolve, reqset)
def test_find_wheel_supported(self, data, monkeypatch): """ Test finding supported wheel. """ monkeypatch.setattr( pip._internal.pep425tags, "get_supported", lambda **kw: [('py2', 'none', 'any')], ) req = install_req_from_line("simple.dist") finder = PackageFinder.create( [data.find_links], [], session=PipSession(), ) found = finder.find_requirement(req, True) assert ( found.url.endswith("simple.dist-0.1-py2.py3-none-any.whl")), found
def test_create__candidate_prefs( self, allow_all_prereleases, prefer_binary, ): """ Test that the _candidate_prefs attribute is set correctly. """ selection_prefs = SelectionPreferences( allow_yanked=True, allow_all_prereleases=allow_all_prereleases, prefer_binary=prefer_binary, ) finder = PackageFinder.create( search_scope=SearchScope([], []), selection_prefs=selection_prefs, session=PipSession(), ) candidate_prefs = finder._candidate_prefs assert candidate_prefs.allow_all_prereleases == allow_all_prereleases assert candidate_prefs.prefer_binary == prefer_binary
def test_hash_mismatch(self, data): """A hash mismatch should raise an error.""" file_url = path_to_url( (data.packages / 'simple-1.0.tar.gz').abspath) reqset = RequirementSet(require_hashes=True) reqset.add_requirement(get_processed_req_from_line( '%s --hash=sha256:badbad' % file_url, lineno=1, )) finder = PackageFinder([data.find_links], [], session=PipSession()) resolver = self._basic_resolver(finder) assert_raises_regexp( HashErrors, r'THESE PACKAGES DO NOT MATCH THE HASHES.*\n' r' file:///.*/data/packages/simple-1\.0\.tar\.gz .*:\n' r' Expected sha256 badbad\n' r' Got 393043e672415891885c9a2a0929b1af95fb866d' r'6ca016b42d2e6ce53619b653$', resolver.resolve, reqset)
def test_create__target_python(self): """ Test that the _target_python attribute is set correctly. """ link_collector = LinkCollector( session=PipSession(), search_scope=SearchScope([], []), ) target_python = TargetPython(py_version_info=(3, 7, 3)) finder = PackageFinder.create( link_collector=link_collector, selection_prefs=SelectionPreferences(allow_yanked=True), target_python=target_python, ) actual_target_python = finder._target_python # The target_python attribute should be set as is. assert actual_target_python is target_python # Check that the attributes weren't reset. assert actual_target_python.py_version_info == (3, 7, 3)
def test_finder_detects_latest_already_satisfied_pypi_links(): """Test PackageFinder detects latest already satisfied using pypi links""" req = install_req_from_line('initools', None) # the latest initools on PyPI is 0.3.1 latest_version = "0.3.1" satisfied_by = Mock( location="/path", parsed_version=parse_version(latest_version), version=latest_version, ) req.satisfied_by = satisfied_by finder = PackageFinder.create( [], ["http://pypi.org/simple/"], session=PipSession(), ) with pytest.raises(BestVersionAlreadyInstalled): finder.find_requirement(req, True)
def _build_package_finder( self, options, # type: Values session, # type: PipSession platform=None, # type: Optional[str] py_version_info=None, # type: Optional[Tuple[int, ...]] abi=None, # type: Optional[str] implementation=None, # type: Optional[str] ignore_requires_python=None, # type: Optional[bool] ): # type: (...) -> PackageFinder """ Create a package finder appropriate to this requirement command. :param ignore_requires_python: Whether to ignore incompatible "Requires-Python" values in links. Defaults to False. """ index_urls = [options.index_url] + options.extra_index_urls if options.no_index: logger.debug( 'Ignoring indexes: %s', ','.join(redact_password_from_url(url) for url in index_urls), ) index_urls = [] target_python = TargetPython( platform=platform, py_version_info=py_version_info, abi=abi, implementation=implementation, ) return PackageFinder.create( find_links=options.find_links, format_control=options.format_control, index_urls=index_urls, trusted_hosts=options.trusted_hosts, allow_all_prereleases=options.pre, session=session, target_python=target_python, prefer_binary=options.prefer_binary, ignore_requires_python=ignore_requires_python, )
def test_missing_hash_checking(self): """Make sure prepare_files() raises an error when a requirement has no hash in implicit hash-checking mode. """ reqset = RequirementSet() # No flags here. This tests that detection of later flags nonetheless # requires earlier packages to have hashes: reqset.add_requirement( list(process_line('blessings==1.0', 'file', 1))[0]) # This flag activates --require-hashes mode: reqset.add_requirement( list( process_line('tracefront==0.1 --hash=sha256:somehash', 'file', 2))[0]) # This hash should be accepted because it came from the reqs file, not # from the internet: reqset.add_requirement( list( process_line( 'https://pypi.python.org/packages/source/m/more-' 'itertools/more-itertools-1.0.tar.gz#md5=b21850c' '3cfa7efbb70fd662ab5413bdd', 'file', 3))[0]) # The error text should list this as a URL and not `peep==3.1.1`: reqset.add_requirement( list( process_line( 'https://pypi.python.org/packages/source/p/peep/' 'peep-3.1.1.tar.gz', 'file', 4))[0]) finder = PackageFinder([], ['https://pypi.python.org/simple'], session=PipSession()) resolver = self._basic_resolver(finder) assert_raises_regexp( HashErrors, r'Hashes are required in --require-hashes mode, but they are ' r'missing .*\n' r' https://pypi\.python\.org/packages/source/p/peep/peep' r'-3\.1\.1\.tar\.gz --hash=sha256:[0-9a-f]+\n' r' blessings==1.0 --hash=sha256:[0-9a-f]+\n' r'THESE PACKAGES DO NOT MATCH THE HASHES.*\n' r' tracefront==0.1 .*:\n' r' Expected sha256 somehash\n' r' Got [0-9a-f]+$', resolver.resolve, reqset)
def create_package_finder(**kwargs): find_links = kwargs.pop('find_links', None) index_urls = kwargs.pop('index_urls', None) allow_all_prereleases = kwargs.pop('allow_all_prereleases', None) if find_links is not None: kwargs.setdefault( 'search_scope', SearchScope( find_links=find_links, index_urls=index_urls, )) if allow_all_prereleases is not None: kwargs.setdefault( 'selection_prefs', SelectionPreferences( allow_yanked=True, allow_all_prereleases=allow_all_prereleases, )) return PackageFinder.create(**kwargs)
def test_not_find_wheel_not_supported(self, data, monkeypatch): """ Test not finding an unsupported wheel. """ monkeypatch.setattr( pip._internal.pep425tags, "get_supported", lambda **kw: [("py1", "none", "any")], ) req = install_req_from_line("simple.dist") finder = PackageFinder.create( [data.find_links], [], session=PipSession(), ) valid_tags = pip._internal.pep425tags.get_supported() finder.candidate_evaluator = CandidateEvaluator(valid_tags=valid_tags) with pytest.raises(DistributionNotFound): finder.find_requirement(req, True)
def test_existing_over_wheel_priority(self, data): """ Test existing install has priority over wheels. `test_link_sorting` also covers this at a lower level """ req = install_req_from_line('priority', None) latest_version = "1.0" satisfied_by = Mock( location="/path", parsed_version=parse_version(latest_version), version=latest_version, ) req.satisfied_by = satisfied_by finder = PackageFinder.create( [data.find_links], [], session=PipSession(), ) with pytest.raises(BestVersionAlreadyInstalled): finder.find_requirement(req, True)
def test_missing_hash_with_require_hashes(self, data): """Setting --require-hashes explicitly should raise errors if hashes are missing. """ reqset = RequirementSet(require_hashes=True) reqset.add_requirement(get_processed_req_from_line( 'simple==1.0', lineno=1 )) finder = PackageFinder([data.find_links], [], session=PipSession()) resolver = self._basic_resolver(finder) assert_raises_regexp( HashErrors, r'Hashes are required in --require-hashes mode, but they are ' r'missing .*\n' r' simple==1.0 --hash=sha256:393043e672415891885c9a2a0929b1af95' r'fb866d6ca016b42d2e6ce53619b653$', resolver.resolve, reqset )
def test_unsupported_hashes(self, data): """VCS and dir links should raise errors when --require-hashes is on. In addition, complaints about the type of requirement (VCS or dir) should trump the presence or absence of a hash. """ reqset = RequirementSet(require_hashes=True) reqset.add_requirement( get_processed_req_from_line( 'git+git://github.com/pypa/pip-test-package --hash=sha256:123', lineno=1, )) dir_path = data.packages.join('FSPkg') reqset.add_requirement( get_processed_req_from_line( 'file://%s' % (dir_path, ), lineno=2, )) finder = PackageFinder.create( [data.find_links], [], session=PipSession(), ) resolver = self._basic_resolver(finder) sep = os.path.sep if sep == '\\': sep = '\\\\' # This needs to be escaped for the regex assert_raises_regexp( HashErrors, r"Can't verify hashes for these requirements because we don't " r"have a way to hash version control repositories:\n" r" git\+git://github\.com/pypa/pip-test-package \(from -r file " r"\(line 1\)\)\n" r"Can't verify hashes for these file:// requirements because they " r"point to directories:\n" r" file://.*{sep}data{sep}packages{sep}FSPkg " r"\(from -r file \(line 2\)\)".format(sep=sep), resolver.resolve, reqset)
def _build_package_finder( self, options, # type: Values session, # type: PipSession platform=None, # type: Optional[str] py_version_info=None, # type: Optional[Tuple[int, ...]] abi=None, # type: Optional[str] implementation=None, # type: Optional[str] ignore_requires_python=None, # type: Optional[bool] ): # type: (...) -> PackageFinder """ Create a package finder appropriate to this requirement command. :param ignore_requires_python: Whether to ignore incompatible "Requires-Python" values in links. Defaults to False. """ search_scope = make_search_scope(options) selection_prefs = SelectionPreferences( allow_yanked=True, format_control=options.format_control, allow_all_prereleases=options.pre, prefer_binary=options.prefer_binary, ignore_requires_python=ignore_requires_python, ) target_python = TargetPython( platform=platform, py_version_info=py_version_info, abi=abi, implementation=implementation, ) return PackageFinder.create( search_scope=search_scope, selection_prefs=selection_prefs, trusted_hosts=options.trusted_hosts, session=session, target_python=target_python, )
def test_create__candidate_evaluator( self, allow_all_prereleases, prefer_binary, ): """ Test that the candidate_evaluator attribute is set correctly. """ selection_prefs = SelectionPreferences( allow_yanked=True, allow_all_prereleases=allow_all_prereleases, prefer_binary=prefer_binary, ) target_python = TargetPython(py_version_info=(3, 7, 3)) target_python._valid_tags = ['tag1', 'tag2'] finder = PackageFinder.create( search_scope=SearchScope([], []), selection_prefs=selection_prefs, session=PipSession(), target_python=target_python, ) evaluator = finder.candidate_evaluator assert evaluator.allow_all_prereleases == allow_all_prereleases assert evaluator._prefer_binary == prefer_binary assert evaluator._supported_tags == ['tag1', 'tag2']
def test_link_sorting_wheels_with_build_tags(self): """Verify build tags affect sorting.""" links = [ InstallationCandidate( "simplewheel", "2.0", Link("simplewheel-2.0-1-py2.py3-none-any.whl"), ), InstallationCandidate( "simplewheel", "2.0", Link("simplewheel-2.0-py2.py3-none-any.whl"), ), InstallationCandidate( "simplewheel", "1.0", Link("simplewheel-1.0-py2.py3-none-any.whl"), ), ] finder = PackageFinder.create([], [], session=PipSession()) sort_key = finder.candidate_evaluator._sort_key results = sorted(links, key=sort_key, reverse=True) results2 = sorted(reversed(links), key=sort_key, reverse=True) assert links == results == results2, results2
def test_finder_only_installs_data_require(data): """ Test whether the PackageFinder understand data-python-requires This can optionally be exposed by a simple-repository to tell which distribution are compatible with which version of Python by adding a data-python-require to the anchor links. See pep 503 for more information. """ # using a local index (that has pre & dev releases) finder = PackageFinder.create( [], [data.index_url("datarequire")], session=PipSession(), ) links = finder.find_all_candidates("fakepackage") expected = ['1.0.0', '9.9.9'] if (2, 7) < sys.version_info < (3,): expected.append('2.7.0') elif sys.version_info > (3, 3): expected.append('3.3.0') assert {str(v.version) for v in links} == set(expected)
def test_create__py_version_info( self, mock_get_supported, py_version_info, expected, ): """ Test that the py_version_info argument is handled correctly. """ expected_versions, expected_evaluator_info = expected finder = PackageFinder.create( [], [], py_version_info=py_version_info, session=object(), ) actual = mock_get_supported.call_args[1]['versions'] assert actual == expected_versions # For candidate_evaluator, we only need to test _py_version_info # since setting _py_version correctly is tested in # TestCandidateEvaluator. evaluator = finder.candidate_evaluator assert evaluator._py_version_info == expected_evaluator_info
def _build_package_finder(self, options, session, platform=None, python_versions=None, abi=None, implementation=None): """ Create a package finder appropriate to this requirement command. """ index_urls = [options.index_url] + options.extra_index_urls if options.no_index: logger.debug('Ignoring indexes: %s', ','.join(index_urls)) index_urls = [] return PackageFinder( find_links=options.find_links, format_control=options.format_control, index_urls=index_urls, trusted_hosts=options.trusted_hosts, allow_all_prereleases=options.pre, process_dependency_links=options.process_dependency_links, session=session, platform=platform, versions=python_versions, abi=abi, implementation=implementation, )
def test_finder_priority_page_over_deplink(): """ Test PackageFinder prefers page links over equivalent dependency links """ req = InstallRequirement.from_line('pip==1.5.6', None) finder = PackageFinder( [], ["https://pypi.python.org/simple"], process_dependency_links=True, session=PipSession(), ) finder.add_dependency_links([ 'https://warehouse.python.org/packages/source/p/pip/pip-1.5.6.tar.gz' ]) all_versions = finder.find_all_candidates(req.name) # Check that the dependency_link is last assert all_versions[-1].location.url.startswith('https://warehouse') link = finder.find_requirement(req, False) assert link.url.startswith("https://pypi"), link
def test_finder_installs_pre_releases_with_version_spec(): """ Test PackageFinder only accepts stable versioned releases by default. """ req = install_req_from_line("bar>=0.0.dev0", None) links = ["https://foo/bar-1.0.tar.gz", "https://foo/bar-2.0b1.tar.gz"] finder = PackageFinder(links, [], session=PipSession()) with patch.object(finder, "_get_pages", lambda x, y: []): link = finder.find_requirement(req, False) assert link.url == "https://foo/bar-1.0.tar.gz" links.reverse() finder = PackageFinder(links, [], session=PipSession()) with patch.object(finder, "_get_pages", lambda x, y: []): link = finder.find_requirement(req, False) assert link.url == "https://foo/bar-1.0.tar.gz"
def pip_version_check(session, options): # type: (PipSession, optparse.Values) -> None """Check for an update for pip. Limit the frequency of checks to once per week. State is stored either in the active virtualenv or in the user's USER_CACHE_DIR keyed off the prefix of the pip script path. """ installed_version = get_installed_version("pip") if not installed_version: return pip_version = packaging_version.parse(installed_version) pypi_version = None try: state = SelfCheckState(cache_dir=options.cache_dir) current_time = datetime.datetime.utcnow() # Determine if we need to refresh the state if "last_check" in state.state and "pypi_version" in state.state: last_check = datetime.datetime.strptime(state.state["last_check"], SELFCHECK_DATE_FMT) if (current_time - last_check).total_seconds() < 7 * 24 * 60 * 60: pypi_version = state.state["pypi_version"] # Refresh the version if we need to or just see if we need to warn if pypi_version is None: # Lets use PackageFinder to see what the latest pip version is finder = PackageFinder( find_links=options.find_links, index_urls=[options.index_url] + options.extra_index_urls, allow_all_prereleases=False, # Explicitly set to False trusted_hosts=options.trusted_hosts, session=session, ) candidate = finder.find_candidates("pip").get_best() if candidate is None: return pypi_version = str(candidate.version) # save that we've performed a check state.save(pypi_version, current_time) remote_version = packaging_version.parse(pypi_version) # Determine if our pypi_version is older if (pip_version < remote_version and pip_version.base_version != remote_version.base_version and was_installed_by_pip('pip')): # Advise "python -m pip" on Windows to avoid issues # with overwriting pip.exe. if WINDOWS: pip_cmd = "python -m pip" else: pip_cmd = "pip" logger.warning( "You are using pip version %s, however version %s is " "available.\nYou should consider upgrading via the " "'%s install --upgrade pip' command.", pip_version, pypi_version, pip_cmd) except Exception: logger.debug( "There was an error checking the latest version of pip", exc_info=True, )
def test_secure_origin(location, trusted, expected): finder = PackageFinder([], [], session=[], trusted_hosts=trusted) logger = MockLogger() finder._validate_secure_origin(logger, location) assert logger.called == expected
def test_no_partial_name_match(data): """Finder requires the full project name to match, not just beginning.""" finder = PackageFinder([data.find_links], [], session=PipSession()) req = InstallRequirement.from_line("gmpy") found = finder.find_requirement(req, False) assert found.url.endswith("gmpy-1.15.tar.gz"), found
def test_no_mpkg(data): """Finder skips zipfiles with "macosx10" in the name.""" finder = PackageFinder([data.find_links], [], session=PipSession()) req = InstallRequirement.from_line("pkgwithmpkg") found = finder.find_requirement(req, False) assert found.url.endswith("pkgwithmpkg-1.0.tar.gz"), found
def test_tilde(): """Finder can accept a path with ~ in it and will normalize it.""" session = PipSession() with patch('pip._internal.index.os.path.exists', return_value=True): finder = PackageFinder(['~/python-pkgs'], [], session=session) req = InstallRequirement.from_line("gmpy") with pytest.raises(DistributionNotFound): finder.find_requirement(req, False)
def test_get_index_urls_locations(): """Check that the canonical name is on all indexes""" finder = PackageFinder( [], ['file://index1/', 'file://index2'], session=PipSession()) locations = finder._get_index_urls_locations( InstallRequirement.from_line('Complex_Name').name) assert locations == ['file://index1/complex-name/', 'file://index2/complex-name/']
def test_duplicates_sort_ok(data): """Finder successfully finds one of a set of duplicates in different locations""" finder = PackageFinder( [data.find_links, data.find_links2], [], session=PipSession(), ) req = InstallRequirement.from_line("duplicate") found = finder.find_requirement(req, False) assert found.url.endswith("duplicate-1.0.tar.gz"), found
def test_wheel_over_sdist_priority(self, data): """ Test wheels have priority over sdists. `test_link_sorting` also covers this at lower level """ req = InstallRequirement.from_line("priority") finder = PackageFinder( [data.find_links], [], session=PipSession(), ) found = finder.find_requirement(req, True) assert found.url.endswith("priority-1.0-py2.py3-none-any.whl"), found
def test_finder_installs_dev_releases(data): """ Test PackageFinder finds dev releases if asked to. """ req = InstallRequirement.from_line("bar", None) # using a local index (that has dev releases) finder = PackageFinder( [], [data.index_url("dev")], allow_all_prereleases=True, session=PipSession(), ) link = finder.find_requirement(req, False) assert link.url.endswith("bar-2.0.dev1.tar.gz"), link.url
def test_finder_detects_latest_already_satisfied_find_links(data): """Test PackageFinder detects latest already satisfied using find-links""" req = InstallRequirement.from_line('simple', None) # the latest simple in local pkgs is 3.0 latest_version = "3.0" satisfied_by = Mock( location="/path", parsed_version=parse_version(latest_version), version=latest_version ) req.satisfied_by = satisfied_by finder = PackageFinder([data.find_links], [], session=PipSession()) with pytest.raises(BestVersionAlreadyInstalled): finder.find_requirement(req, True)
def test_finder_priority_file_over_page(data): """Test PackageFinder prefers file links over equivalent page links""" req = InstallRequirement.from_line('gmpy==1.15', None) finder = PackageFinder( [data.find_links], ["http://pypi.python.org/simple"], session=PipSession(), ) all_versions = finder.find_all_candidates(req.name) # 1 file InstallationCandidate followed by all https ones assert all_versions[0].location.scheme == 'file' assert all(version.location.scheme == 'https' for version in all_versions[1:]), all_versions link = finder.find_requirement(req, False) assert link.url.startswith("file://")
def test_finder_priority_nonegg_over_eggfragments(): """Test PackageFinder prefers non-egg links over "#egg=" links""" req = InstallRequirement.from_line('bar==1.0', None) links = ['http://foo/bar.py#egg=bar-1.0', 'http://foo/bar-1.0.tar.gz'] finder = PackageFinder(links, [], session=PipSession()) with patch.object(finder, "_get_pages", lambda x, y: []): all_versions = finder.find_all_candidates(req.name) assert all_versions[0].location.url.endswith('tar.gz') assert all_versions[1].location.url.endswith('#egg=bar-1.0') link = finder.find_requirement(req, False) assert link.url.endswith('tar.gz') links.reverse() finder = PackageFinder(links, [], session=PipSession()) with patch.object(finder, "_get_pages", lambda x, y: []): all_versions = finder.find_all_candidates(req.name) assert all_versions[0].location.url.endswith('tar.gz') assert all_versions[1].location.url.endswith('#egg=bar-1.0') link = finder.find_requirement(req, False) assert link.url.endswith('tar.gz')
def test_finder_only_installs_stable_releases(data): """ Test PackageFinder only accepts stable versioned releases by default. """ req = InstallRequirement.from_line("bar", None) # using a local index (that has pre & dev releases) finder = PackageFinder([], [data.index_url("pre")], session=PipSession()) link = finder.find_requirement(req, False) assert link.url.endswith("bar-1.0.tar.gz"), link.url # using find-links links = ["https://foo/bar-1.0.tar.gz", "https://foo/bar-2.0b1.tar.gz"] finder = PackageFinder(links, [], session=PipSession()) with patch.object(finder, "_get_pages", lambda x, y: []): link = finder.find_requirement(req, False) assert link.url == "https://foo/bar-1.0.tar.gz" links.reverse() finder = PackageFinder(links, [], session=PipSession()) with patch.object(finder, "_get_pages", lambda x, y: []): link = finder.find_requirement(req, False) assert link.url == "https://foo/bar-1.0.tar.gz"
def test_finder_deplink(): """ Test PackageFinder with dependency links only """ req = InstallRequirement.from_line('gmpy==1.15', None) finder = PackageFinder( [], [], process_dependency_links=True, session=PipSession(), ) finder.add_dependency_links( ['https://pypi.python.org/packages/source/g/gmpy/gmpy-1.15.zip']) link = finder.find_requirement(req, False) assert link.url.startswith("https://pypi"), link