Example #1
0
class MockPackageFinder:

    BASE_URL = "https://pypi.org/simple/pip-{0}.tar.gz"
    PIP_PROJECT_NAME = "pip"
    INSTALLATION_CANDIDATES = [
        InstallationCandidate(
            PIP_PROJECT_NAME,
            "6.9.0",
            Link(BASE_URL.format("6.9.0")),
        ),
        InstallationCandidate(
            PIP_PROJECT_NAME,
            "3.3.1",
            Link(BASE_URL.format("3.3.1")),
        ),
        InstallationCandidate(
            PIP_PROJECT_NAME,
            "1.0",
            Link(BASE_URL.format("1.0")),
        ),
    ]

    @classmethod
    def create(cls, *args: Any, **kwargs: Any) -> "MockPackageFinder":
        return cls()

    def find_best_candidate(self,
                            project_name: str) -> MockBestCandidateResult:
        return MockBestCandidateResult(self.INSTALLATION_CANDIDATES[0])
Example #2
0
class MockPackageFinder(object):

    BASE_URL = 'https://pypi.org/simple/pip-{0}.tar.gz'
    PIP_PROJECT_NAME = 'pip'
    INSTALLATION_CANDIDATES = [
        InstallationCandidate(PIP_PROJECT_NAME, '6.9.0',
                              BASE_URL.format('6.9.0')),
        InstallationCandidate(PIP_PROJECT_NAME, '3.3.1',
                              BASE_URL.format('3.3.1')),
        InstallationCandidate(PIP_PROJECT_NAME, '1.0', BASE_URL.format('1.0')),
    ]

    @classmethod
    def create(cls, *args, **kwargs):
        return cls()

    def find_best_candidate(self, project_name):
        return MockBestCandidateResult(self.INSTALLATION_CANDIDATES[0])
 def setUp(self):
     candidates = []
     for version in canned_versions:
         url = "https://foo:12345/repository/unittest-{}.tgz#md5=4711".format(
             version)
         url = Link(url)
         candidate = InstallationCandidate('unittest', version, url)
         candidates.append(candidate)
     self.canned_candidates = candidates
Example #4
0
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
Example #5
0
def make_mock_candidate(version, yanked_reason=None, hex_digest=None):
    url = f"https://example.com/pkg-{version}.tar.gz"
    if hex_digest is not None:
        assert len(hex_digest) == 64
        url += f"#sha256={hex_digest}"

    link = Link(url, yanked_reason=yanked_reason)
    candidate = InstallationCandidate("mypackage", version, link)

    return candidate
Example #6
0
    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
Example #7
0
    def test_collect_sources(
        self, caplog: pytest.LogCaptureFixture, data: TestData
    ) -> None:
        caplog.set_level(logging.DEBUG)

        link_collector = make_test_link_collector(
            find_links=[data.find_links],
            # Include two copies of the URL to check that the second one
            # is skipped.
            index_urls=[PyPI.simple_url, PyPI.simple_url],
        )
        collected_sources = link_collector.collect_sources(
            "twine",
            candidates_from_page=lambda link: [
                InstallationCandidate("twine", "1.0", link)
            ],
        )

        files_it = itertools.chain.from_iterable(
            source.file_links()
            for sources in collected_sources
            for source in sources
            if source is not None
        )
        pages_it = itertools.chain.from_iterable(
            source.page_candidates()
            for sources in collected_sources
            for source in sources
            if source is not None
        )
        files = list(files_it)
        pages = list(pages_it)

        # Spot-check the returned sources.
        assert len(files) > 20
        check_links_include(files, names=["simple-1.0.tar.gz"])

        assert [page.link for page in pages] == [Link("https://pypi.org/simple/twine/")]
        # Check that index URLs are marked as *un*cacheable.
        assert not pages[0].link.cache_link_parsing

        expected_message = dedent(
            """\
        1 location(s) to search for versions of twine:
        * https://pypi.org/simple/twine/"""
        )
        assert caplog.record_tuples == [
            ("pip._internal.index.collector", logging.DEBUG, expected_message),
        ]
Example #8
0
def test_provider_known_depths(factory: Factory) -> None:
    # Root requirement is specified by the user
    # therefore has an infered depth of 1
    root_requirement_name = "my-package"
    provider = PipProvider(
        factory=factory,
        constraints={},
        ignore_dependencies=False,
        upgrade_strategy="to-satisfy-only",
        user_requested={root_requirement_name: 0},
    )

    root_requirement_information = build_requirement_information(
        name=root_requirement_name, parent=None)
    provider.get_preference(
        identifier=root_requirement_name,
        resolutions={},
        candidates={},
        information={root_requirement_name: root_requirement_information},
        backtrack_causes=[],
    )
    assert provider._known_depths == {root_requirement_name: 1.0}

    # Transative requirement is a dependency of root requirement
    # theforefore has an infered depth of 2
    root_package_candidate = InstallationCandidate(
        root_requirement_name,
        "1.0",
        Link("https://{root_requirement_name}.com"),
    )
    transative_requirement_name = "my-transitive-package"

    transative_package_information = build_requirement_information(
        name=transative_requirement_name, parent=root_package_candidate)
    provider.get_preference(
        identifier=transative_requirement_name,
        resolutions={},
        candidates={},
        information={
            root_requirement_name: root_requirement_information,
            transative_requirement_name: transative_package_information,
        },
        backtrack_causes=[],
    )
    assert provider._known_depths == {
        transative_requirement_name: 2.0,
        root_requirement_name: 1.0,
    }
Example #9
0
    def get_install_candidate(self, link_evaluator: LinkEvaluator,
                              link: Link) -> Optional[InstallationCandidate]:
        """
        If the link is a candidate for install, convert it to an
        InstallationCandidate and return it. Otherwise, return None.
        """
        result, detail = link_evaluator.evaluate_link(link)
        if result != LinkType.candidate:
            self._log_skipped_link(link, result, detail)
            return None

        return InstallationCandidate(
            name=link_evaluator.project_name,
            link=link,
            version=detail,
        )
Example #10
0
    def find_best_match(self, ireq, prereleases=False):
        if ireq.editable:
            return ireq

        versions = list(
            ireq.specifier.filter(
                self.index[key_from_ireq(ireq)], prereleases=prereleases
            )
        )
        if not versions:
            tried_versions = [
                InstallationCandidate(ireq.name, version, "https://fake.url.foo")
                for version in self.index[key_from_ireq(ireq)]
            ]
            raise NoCandidateFound(ireq, tried_versions, ["https://fake.url.foo"])
        best_version = max(versions, key=Version)
        return make_install_requirement(key_from_ireq(ireq), best_version, ireq)
Example #11
0
    def get_install_candidate(self, link, search):
        # type: (Link, Search) -> Optional[InstallationCandidate]
        """
        If the link is a candidate for install, convert it to an
        InstallationCandidate and return it. Otherwise, return None.
        """
        is_candidate, result = self._evaluate_link(link, search=search)
        if not is_candidate:
            if result:
                self._log_skipped_link(link, reason=result)
            return None

        return InstallationCandidate(
            search.supplied,
            location=link,
            version=result,
        )
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
Example #13
0
    def get_install_candidate(self, link_evaluator, link):
        # type: (LinkEvaluator, Link) -> Optional[InstallationCandidate]
        """
        If the link is a candidate for install, convert it to an
        InstallationCandidate and return it. Otherwise, return None.
        """
        is_candidate, result = link_evaluator.evaluate_link(link)
        if not is_candidate:
            if result:
                self._log_skipped_link(link, reason=result)
            return None

        return InstallationCandidate(
            name=link_evaluator.project_name,
            link=link,
            version=result,
        )
Example #14
0
    def get_install_candidate(self, link, search):
        # type: (Link, Search) -> Optional[InstallationCandidate]
        """
        If the link is a candidate for install, convert it to an
        InstallationCandidate and return it. Otherwise, return None.
        """
        is_candidate, result = (
            self.candidate_evaluator.evaluate_link(link, search=search)
        )
        if not is_candidate:
            if result:
                self._log_skipped_link(link, reason=result)
            return None

        return InstallationCandidate(
            # Convert the Text result to str since InstallationCandidate
            # accepts str.
            search.supplied, location=link, version=str(result),
        )
Example #15
0
    def get_install_candidate(self, link_evaluator, link):
        # type: (LinkEvaluator, Link) -> Optional[InstallationCandidate]
        """
        If the link is a candidate for install, convert it to an
        InstallationCandidate and return it. Otherwise, return None.
        """
        is_candidate, result = link_evaluator.evaluate_link(link)
        if not is_candidate:
            if result:
                self._log_skipped_link(link, reason=result)
            return None

        return InstallationCandidate(
            project=link_evaluator.project_name,
            location=link,
            # Convert the Text result to str since InstallationCandidate
            # accepts str.
            version=str(result),
        )
Example #16
0
    def evaluate_link(self, link, search):
        # type: (Link, Search) -> Optional[InstallationCandidate]
        """
        Determine whether a link is a candidate for installation.

        Returns an InstallationCandidate if so, otherwise None.
        """
        version = None
        if link.egg_fragment:
            egg_info = link.egg_fragment
            ext = link.ext
        else:
            egg_info, ext = link.splitext()
            if not ext:
                self._log_skipped_link(link, 'not a file')
                return None
            if ext not in SUPPORTED_EXTENSIONS:
                self._log_skipped_link(
                    link,
                    'unsupported archive format: %s' % ext,
                )
                return None
            if "binary" not in search.formats and ext == WHEEL_EXTENSION:
                self._log_skipped_link(
                    link,
                    'No binaries permitted for %s' % search.supplied,
                )
                return None
            if "macosx10" in link.path and ext == '.zip':
                self._log_skipped_link(link, 'macosx10 one')
                return None
            if ext == WHEEL_EXTENSION:
                try:
                    wheel = Wheel(link.filename)
                except InvalidWheelFilename:
                    self._log_skipped_link(link, 'invalid wheel filename')
                    return None
                if canonicalize_name(wheel.name) != search.canonical:
                    self._log_skipped_link(
                        link, 'wrong project name (not %s)' % search.supplied)
                    return None

                if not self._is_wheel_supported(wheel):
                    self._log_skipped_link(
                        link, 'it is not compatible with this Python')
                    return None

                version = wheel.version

        # This should be up by the search.ok_binary check, but see issue 2700.
        if "source" not in search.formats and ext != WHEEL_EXTENSION:
            self._log_skipped_link(
                link,
                'No sources permitted for %s' % search.supplied,
            )
            return None

        if not version:
            version = _egg_info_matches(egg_info, search.canonical)
        if not version:
            self._log_skipped_link(
                link, 'Missing project version for %s' % search.supplied)
            return None

        match = self._py_version_re.search(version)
        if match:
            version = version[:match.start()]
            py_version = match.group(1)
            if py_version != sys.version[:3]:
                self._log_skipped_link(link, 'Python version is incorrect')
                return None
        try:
            support_this_python = check_requires_python(
                link.requires_python,
                version_info=sys.version_info[:3],
            )
        except specifiers.InvalidSpecifier:
            logger.debug("Package %s has an invalid Requires-Python entry: %s",
                         link.filename, link.requires_python)
            support_this_python = True

        if not support_this_python:
            logger.debug(
                "The package %s is incompatible with the python "
                "version in use. Acceptable python versions are: %s", link,
                link.requires_python)
            return None
        logger.debug('Found link %s, version: %s', link, version)

        return InstallationCandidate(search.supplied, version, link)
Example #17
0
    def _link_package_versions(self, link, search):
        """Return an InstallationCandidate or None"""
        version = None
        if link.egg_fragment:
            egg_info = link.egg_fragment
            ext = link.ext
        else:
            egg_info, ext = link.splitext()
            if not ext:
                self._log_skipped_link(link, "not a file")
                return
            if ext not in SUPPORTED_EXTENSIONS:
                self._log_skipped_link(link,
                                       "unsupported archive format: %s" % ext)
                return
            if "binary" not in search.formats and ext == wheel_ext:
                self._log_skipped_link(
                    link, "No binaries permitted for %s" % search.supplied)
                return
            if "macosx10" in link.path and ext == ".zip":
                self._log_skipped_link(link, "macosx10 one")
                return
            if ext == wheel_ext:
                try:
                    wheel = Wheel(link.filename)
                except InvalidWheelFilename:
                    self._log_skipped_link(link, "invalid wheel filename")
                    return
                if canonicalize_name(wheel.name) != search.canonical:
                    self._log_skipped_link(
                        link, "wrong project name (not %s)" % search.supplied)
                    return

                if not wheel.supported(self.valid_tags):
                    self._log_skipped_link(
                        link, "it is not compatible with this Python")
                    return

                version = wheel.version

        # This should be up by the search.ok_binary check, but see issue 2700.
        if "source" not in search.formats and ext != wheel_ext:
            self._log_skipped_link(
                link, "No sources permitted for %s" % search.supplied)
            return

        if not version:
            version = egg_info_matches(egg_info, search.supplied, link)
        if version is None:
            self._log_skipped_link(
                link, "Missing project version for %s" % search.supplied)
            return

        match = self._py_version_re.search(version)
        if match:
            version = version[:match.start()]
            py_version = match.group(1)
            if py_version != sys.version[:3]:
                self._log_skipped_link(link, "Python version is incorrect")
                return
        try:
            support_this_python = check_requires_python(link.requires_python)
        except specifiers.InvalidSpecifier:
            logger.debug(
                "Package %s has an invalid Requires-Python entry: %s",
                link.filename,
                link.requires_python,
            )
            support_this_python = True

        if not support_this_python:
            logger.debug(
                "The package %s is incompatible with the python"
                "version in use. Acceptable python versions are:%s",
                link,
                link.requires_python,
            )
            return
        logger.debug("Found link %s, version: %s", link, version)

        return InstallationCandidate(search.supplied, version, link)
Example #18
0
    def make_mock_candidate(self, version, yanked_reason=None):
        url = 'https://example.com/pkg-{}.tar.gz'.format(version)
        link = Link(url, yanked_reason=yanked_reason)
        candidate = InstallationCandidate('mypackage', version, link)

        return candidate