def get_location(self, dist, dependency_links): for url in dependency_links: egg_fragment = Link(url).egg_fragment if not egg_fragment: continue if '-' in egg_fragment: # FIXME: will this work when a package has - in the name? key = '-'.join(egg_fragment.split('-')[:-1]).lower() else: key = egg_fragment if key == dist.key: return url.split('#', 1)[0] return None
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'), ), ] valid_tags = [ ('pyT', 'none', 'TEST'), ('pyT', 'TEST', 'any'), ('pyT', 'none', 'any'), ] specifier = SpecifierSet() evaluator = CandidateEvaluator( 'my-project', supported_tags=valid_tags, specifier=specifier, ) sort_key = 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 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_request_retries(caplog): caplog.set_level(logging.DEBUG) link = Link('http://localhost') session = Mock(PipSession) session.get.side_effect = requests.exceptions.RetryError('Retry error') assert _get_html_page(link, session=session) is None assert ( 'Could not fetch URL http://localhost: Retry error - skipping' in caplog.text )
def test_evaluate_link__substring_fails(self, url, expected_msg): """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'], ) actual = self.evaluator.evaluate_link(link, search) assert actual == (False, expected_msg)
def make_mock_candidate(version, yanked_reason=None, hex_digest=None): url = 'https://example.com/pkg-{}.tar.gz'.format(version) if hex_digest is not None: assert len(hex_digest) == 64 url += '#sha256={}'.format(hex_digest) link = Link(url, yanked_reason=yanked_reason) candidate = InstallationCandidate('mypackage', version, link) return candidate
def test_evaluate_link__match(self, url, expected_version): """Test that 'pytest' archives match for 'pytest'""" link = Link(url) search = Search( supplied=self.search_name, canonical=self.canonical_name, formats=['source', 'binary'], ) actual = self.evaluator.evaluate_link(link, search) assert actual == (True, expected_version)
def test_request_http_error(caplog): caplog.set_level(logging.DEBUG) link = Link('http://localhost') session = Mock(PipSession) session.get.return_value = resp = Mock() resp.raise_for_status.side_effect = requests.HTTPError('Http error') assert _get_html_page(link, session=session) is None assert ( 'Could not fetch URL http://localhost: Http error - skipping' in caplog.text )
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
def test_evaluate_link__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.evaluator.get_install_candidate(link, search) expected = InstallationCandidate(self.search_name, self.version, link) assert result == expected, result
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_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'), ), ] valid_tags = [ ('pyT', 'none', 'TEST'), ('pyT', 'TEST', 'any'), ('pyT', 'none', 'any'), ] target_python = TargetPython() target_python._valid_tags = valid_tags evaluator = CandidateEvaluator(target_python=target_python) sort_key = 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_check_link_requires_python__invalid_requires(caplog): """ Test the log message for an invalid Requires-Python. """ link = Link('https://example.com', requires_python='invalid') caplog.set_level(logging.DEBUG) actual = _check_link_requires_python(link, version_info=(3, 6, 5)) assert actual expected_message = ( "Ignoring invalid Requires-Python ('invalid') for link: " "https://example.com") check_caplog(caplog, 'DEBUG', expected_message)
def test_sort_key__is_yanked(self, yanked_reason, expected): """ Test the effect of is_yanked on _sort_key()'s return value. """ url = 'https://example.com/mypackage.tar.gz' link = Link(url, yanked_reason=yanked_reason) candidate = InstallationCandidate('mypackage', '1.0', link) evaluator = CandidateEvaluator() sort_value = evaluator._sort_key(candidate) # Yanked / non-yanked is reflected in the first element of the tuple. actual = sort_value[0] assert actual == expected
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 optimistic_wheel_search(req, index_urls): name = req.name.replace('-', '_').lower() for index_url in index_urls: expected_location = os.path.join( CACHE.wheelhouse, index_url, ignorecase_glob(name) + '-*.whl', ) for link in glob.glob(expected_location): link = Link('file:' + link) wheel = Wheel(link.filename) if req.specifier.contains(wheel.version) and wheel.supported(): return link
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_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_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"), ), ] candidate_evaluator = CandidateEvaluator.create('my-project') sort_key = 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_fragments(self): url = 'git+https://example.com/package#egg=eggname' assert 'eggname' == Link(url).egg_fragment assert None is Link(url).subdirectory_fragment url = 'git+https://example.com/package#egg=eggname&subdirectory=subdir' assert 'eggname' == Link(url).egg_fragment assert 'subdir' == Link(url).subdirectory_fragment url = 'git+https://example.com/package#subdirectory=subdir&egg=eggname' assert 'eggname' == Link(url).egg_fragment assert 'subdir' == Link(url).subdirectory_fragment
def test_get_html_page_invalid_scheme(caplog, url, vcs_scheme): """`_get_html_page()` should error if an invalid scheme is given. Only file:, http:, https:, and ftp: are allowed. """ with caplog.at_level(logging.DEBUG): page = _get_html_page(Link(url), session=mock.Mock(PipSession)) assert page is None assert caplog.record_tuples == [ ( "pip._internal.index", logging.DEBUG, "Cannot look at {} URL {}".format(vcs_scheme, url), ), ]
def test_get_html_page_directory_append_index(tmpdir): """`_get_html_page()` should append "index.html" to a directory URL. """ dirpath = tmpdir.mkdir("something") dir_url = "file:///{}".format( urllib_request.pathname2url(dirpath).lstrip("/"), ) session = mock.Mock(PipSession) with mock.patch("pip._internal.index._get_html_response") as mock_func: _get_html_page(Link(dir_url), session=session) assert mock_func.mock_calls == [ mock.call( "{}/index.html".format(dir_url.rstrip("/")), session=session, ), ]
def test_check_link_requires_python__incompatible_python( caplog, ignore_requires_python, expected, ): """ Test an incompatible Python. """ expected_return, expected_level, expected_message = expected link = Link('https://example.com', requires_python='== 3.6.4') caplog.set_level(logging.DEBUG) actual = _check_link_requires_python( link, version_info=(3, 6, 5), ignore_requires_python=ignore_requires_python, ) assert actual == expected_return check_caplog(caplog, expected_level, expected_message)
def test_evaluate_link__allow_yanked( self, yanked_reason, allow_yanked, expected, ): target_python = TargetPython(py_version_info=(3, 6, 4)) evaluator = LinkEvaluator( project_name='twine', canonical_name='twine', formats={'source'}, target_python=target_python, allow_yanked=allow_yanked, ) link = Link( 'https://example.com/#egg=twine-1.12', yanked_reason=yanked_reason, ) actual = evaluator.evaluate_link(link) assert actual == expected
def _pip_query_pypi_json(resconfig): package_name = resconfig['source']['name'] index_url, unused_hostname = get_pypi_url(resconfig) url = '{}/{}/json'.format(index_url, package_name) response = requests.get(url) if response.ok: candidates = [] data = response.json() for version, release_artefacts in data['releases'].items(): for release in release_artefacts: candidates.append( InstallationCandidate(package_name, version, Link(release['url']))) return candidates return None
def test_evaluate_link__allow_yanked( self, yanked_reason, allow_yanked, expected, ): evaluator = CandidateEvaluator(allow_yanked=allow_yanked) link = Link( 'https://example.com/#egg=twine-1.12', yanked_reason=yanked_reason, ) search = Search( supplied='twine', canonical='twine', formats=['source'], ) actual = evaluator.evaluate_link(link, search=search) assert actual == expected
def test_evaluate_link( self, py_version_info, ignore_requires_python, expected, ): target_python = TargetPython(py_version_info=py_version_info) evaluator = LinkEvaluator( project_name='twine', canonical_name='twine', formats={'source'}, target_python=target_python, allow_yanked=True, ignore_requires_python=ignore_requires_python, ) link = Link( 'https://example.com/#egg=twine-1.12', requires_python='== 3.6.5', ) actual = evaluator.evaluate_link(link) assert actual == expected
def test_evaluate_link__incompatible_wheel(self): """ Test an incompatible wheel. """ target_python = TargetPython(py_version_info=(3, 6, 4)) # Set the valid tags to an empty list to make sure nothing matches. target_python._valid_tags = [] evaluator = CandidateEvaluator(target_python=target_python) link = Link('https://example.com/sample-1.0-py2.py3-none-any.whl') search = Search( supplied='sample', canonical='sample', formats=['binary'], ) actual = evaluator.evaluate_link(link, search=search) expected = ( False, "none of the wheel's tags match: py2-none-any, py3-none-any") assert actual == expected
def test_evaluate_link__incompatible_wheel(self): """ Test an incompatible wheel. """ target_python = TargetPython(py_version_info=(3, 6, 4)) # Set the valid tags to an empty list to make sure nothing matches. target_python._valid_tags = [] evaluator = LinkEvaluator( project_name='sample', canonical_name='sample', formats={'binary'}, target_python=target_python, allow_yanked=True, ) link = Link('https://example.com/sample-1.0-py2.py3-none-any.whl') actual = evaluator.evaluate_link(link) expected = ( False, "none of the wheel's tags match: py2-none-any, py3-none-any") assert actual == expected
def test_unpack_http_url_bad_downloaded_checksum(mock_unpack_file): """ If already-downloaded file has bad checksum, re-download. """ base_url = 'http://www.example.com/somepackage.tgz' contents = b'downloaded' download_hash = hashlib.new('sha1', contents) link = Link(base_url + '#sha1=' + download_hash.hexdigest()) session = Mock() session.get = Mock() response = session.get.return_value = MockResponse(contents) response.headers = {'content-type': 'application/x-tar'} response.url = base_url download_dir = mkdtemp() try: downloaded_file = os.path.join(download_dir, 'somepackage.tgz') create_file(downloaded_file, 'some contents') unpack_http_url( link, 'location', download_dir=download_dir, session=session, hashes=Hashes({'sha1': [download_hash.hexdigest()]}) ) # despite existence of downloaded file with bad hash, downloaded again session.get.assert_called_once_with( 'http://www.example.com/somepackage.tgz', headers={"Accept-Encoding": "identity"}, stream=True, ) # cached file is replaced with newly downloaded file with open(downloaded_file) as fh: assert fh.read() == 'downloaded' finally: rmtree(download_dir)
def test_evaluate_link( self, py_version_info, ignore_requires_python, expected, ): link = Link( 'https://example.com/#egg=twine-1.12', requires_python='== 3.6.5', ) search = Search( supplied='twine', canonical='twine', formats=['source'], ) evaluator = CandidateEvaluator( [], py_version_info=py_version_info, ignore_requires_python=ignore_requires_python, ) actual = evaluator.evaluate_link(link, search=search) assert actual == expected