Esempio n. 1
0
 def test_not_supported_osx_version(self):
     """
     Wheels built for macOS 10.9 are not supported on 10.6
     """
     tags = pep425tags.get_supported(['27'], False)
     w = wheel.Wheel('simple-0.1-cp27-none-macosx_10_9_intel.whl')
     assert not w.supported(tags=tags)
Esempio n. 2
0
    def test_not_supported_multiarch_darwin(self):
        """
        Single-arch wheels (x86_64) are not supported on multi-arch (intel)
        """
        with patch('pip._internal.pep425tags.get_platform',
                   lambda: 'macosx_10_5_universal'):
            universal = pep425tags.get_supported(['27'], False)
        with patch('pip._internal.pep425tags.get_platform',
                   lambda: 'macosx_10_5_intel'):
            intel = pep425tags.get_supported(['27'], False)

        w = wheel.Wheel('simple-0.1-cp27-none-macosx_10_5_i386.whl')
        assert not w.supported(tags=intel)
        assert not w.supported(tags=universal)
        w = wheel.Wheel('simple-0.1-cp27-none-macosx_10_5_x86_64.whl')
        assert not w.supported(tags=intel)
        assert not w.supported(tags=universal)
Esempio n. 3
0
 def support_index_min(self, tags=None):
     """
     Return the lowest index that one of the wheel's file_tag combinations
     achieves in the supported_tags list e.g. if there are 8 supported tags,
     and one of the file tags is first in the list, then return 0.  Returns
     None is the wheel is not supported.
     """
     if tags is None:  # for mock
         tags = pep425tags.get_supported()
     indexes = [tags.index(c) for c in self.file_tags if c in tags]
     return min(indexes) if indexes else None
Esempio n. 4
0
    def test_manylinux2010_implies_manylinux1(self, manylinux2010, manylinux1):
        """
        Specifying manylinux2010 implies manylinux1.
        """
        groups = {}
        supported = pep425tags.get_supported(platform=manylinux2010)
        for pyimpl, abi, arch in supported:
            groups.setdefault((pyimpl, abi), []).append(arch)

        for arches in groups.values():
            if arches == ['any']:
                continue
            assert arches[:2] == [manylinux2010, manylinux1]
Esempio n. 5
0
    def test_manylinux1_tag_is_first(self):
        """
        Test that the more specific tag manylinux1 comes first.
        """
        groups = {}
        for pyimpl, abi, arch in pep425tags.get_supported():
            groups.setdefault((pyimpl, abi), []).append(arch)

        for arches in groups.values():
            if arches == ['any']:
                continue
            # Expect the most specific arch first:
            if len(arches) == 3:
                assert arches == ['manylinux1_x86_64', 'linux_x86_64', 'any']
            else:
                assert arches == ['manylinux1_x86_64', 'linux_x86_64']
Esempio n. 6
0
    def test_supported_multiarch_darwin(self):
        """
        Multi-arch wheels (intel) are supported on components (i386, x86_64)
        """
        with patch('pip._internal.pep425tags.get_platform',
                   lambda: 'macosx_10_5_universal'):
            universal = pep425tags.get_supported(['27'], False)
        with patch('pip._internal.pep425tags.get_platform',
                   lambda: 'macosx_10_5_intel'):
            intel = pep425tags.get_supported(['27'], False)
        with patch('pip._internal.pep425tags.get_platform',
                   lambda: 'macosx_10_5_x86_64'):
            x64 = pep425tags.get_supported(['27'], False)
        with patch('pip._internal.pep425tags.get_platform',
                   lambda: 'macosx_10_5_i386'):
            i386 = pep425tags.get_supported(['27'], False)
        with patch('pip._internal.pep425tags.get_platform',
                   lambda: 'macosx_10_5_ppc'):
            ppc = pep425tags.get_supported(['27'], False)
        with patch('pip._internal.pep425tags.get_platform',
                   lambda: 'macosx_10_5_ppc64'):
            ppc64 = pep425tags.get_supported(['27'], False)

        w = wheel.Wheel('simple-0.1-cp27-none-macosx_10_5_intel.whl')
        assert w.supported(tags=intel)
        assert w.supported(tags=x64)
        assert w.supported(tags=i386)
        assert not w.supported(tags=universal)
        assert not w.supported(tags=ppc)
        assert not w.supported(tags=ppc64)
        w = wheel.Wheel('simple-0.1-cp27-none-macosx_10_5_universal.whl')
        assert w.supported(tags=universal)
        assert w.supported(tags=intel)
        assert w.supported(tags=x64)
        assert w.supported(tags=i386)
        assert w.supported(tags=ppc)
        assert w.supported(tags=ppc64)
Esempio n. 7
0
    def __init__(self, find_links, index_urls, allow_all_prereleases=False,
                 trusted_hosts=None, process_dependency_links=False,
                 session=None, format_control=None, platform=None,
                 versions=None, abi=None, implementation=None):
        """Create a PackageFinder.

        :param format_control: A FormatControl object or None. Used to control
            the selection of source packages / binary packages when consulting
            the index and links.
        :param platform: A string or None. If None, searches for packages
            that are supported by the current system. Otherwise, will find
            packages that can be built on the platform passed in. These
            packages will only be downloaded for distribution: they will
            not be built locally.
        :param versions: A list of strings or None. This is passed directly
            to pep425tags.py in the get_supported() method.
        :param abi: A string or None. This is passed directly
            to pep425tags.py in the get_supported() method.
        :param implementation: A string or None. This is passed directly
            to pep425tags.py in the get_supported() method.
        """
        if session is None:
            raise TypeError(
                "PackageFinder() missing 1 required keyword argument: "
                "'session'"
            )

        # Build find_links. If an argument starts with ~, it may be
        # a local file relative to a home directory. So try normalizing
        # it and if it exists, use the normalized version.
        # This is deliberately conservative - it might be fine just to
        # blindly normalize anything starting with a ~...
        self.find_links = []
        for link in find_links:
            if link.startswith('~'):
                new_link = normalize_path(link)
                if os.path.exists(new_link):
                    link = new_link
            self.find_links.append(link)

        self.index_urls = index_urls
        self.dependency_links = []

        # These are boring links that have already been logged somehow:
        self.logged_links = set()

        self.format_control = format_control or FormatControl(set(), set())

        # Domains that we won't emit warnings for when not using HTTPS
        self.secure_origins = [
            ("*", host, "*")
            for host in (trusted_hosts if trusted_hosts else [])
        ]

        # Do we want to allow _all_ pre-releases?
        self.allow_all_prereleases = allow_all_prereleases

        # Do we process dependency links?
        self.process_dependency_links = process_dependency_links

        # The Session we'll use to make requests
        self.session = session

        # The valid tags to check potential found wheel candidates against
        self.valid_tags = get_supported(
            versions=versions,
            platform=platform,
            abi=abi,
            impl=implementation,
        )

        # If we don't have TLS enabled, then WARN if anyplace we're looking
        # relies on TLS.
        if not HAS_TLS:
            for link in itertools.chain(self.index_urls, self.find_links):
                parsed = urllib_parse.urlparse(link)
                if parsed.scheme == "https":
                    logger.warning(
                        "pip is configured with locations that require "
                        "TLS/SSL, however the ssl module in Python is not "
                        "available."
                    )
                    break
Esempio n. 8
0
 def supported(self, tags=None):
     """Is this wheel supported on this system?"""
     if tags is None:  # for mock
         tags = pep425tags.get_supported()
     return bool(set(tags).intersection(self.file_tags))
Esempio n. 9
0
 def supported(self, tags=None):
     # type: (Optional[List[Pep425Tag]]) -> bool
     """Is this wheel supported on this system?"""
     if tags is None:  # for mock
         tags = pep425tags.get_supported()
     return bool(set(tags).intersection(self.file_tags))
Esempio n. 10
0
 def supported(self, tags=None):
     # type: (Optional[List[Pep425Tag]]) -> bool
     """Is this wheel supported on this system?"""
     if tags is None:  # for mock
         tags = pep425tags.get_supported()
     return bool(set(tags).intersection(self.file_tags))
Esempio n. 11
0
    def add_requirement(
        self,
        install_req,  # type: InstallRequirement
        parent_req_name=None,  # type: Optional[str]
        extras_requested=None  # type: Optional[Iterable[str]]
    ):
        # type: (...) -> Tuple[List[InstallRequirement], Optional[InstallRequirement]]  # noqa: E501
        """Add install_req as a requirement to install.

        :param parent_req_name: The name of the requirement that needed this
            added. The name is used because when multiple unnamed requirements
            resolve to the same name, we could otherwise end up with dependency
            links that point outside the Requirements set. parent_req must
            already be added. Note that None implies that this is a user
            supplied requirement, vs an inferred one.
        :param extras_requested: an iterable of extras used to evaluate the
            environment markers.
        :return: Additional requirements to scan. That is either [] if
            the requirement is not applicable, or [install_req] if the
            requirement is applicable and has just been added.
        """
        # If the markers do not match, ignore this requirement.
        if not install_req.match_markers(extras_requested):
            logger.info(
                "Ignoring %s: markers '%s' don't match your environment",
                install_req.name,
                install_req.markers,
            )
            return [], None

        # If the wheel is not supported, raise an error.
        # Should check this after filtering out based on environment markers to
        # allow specifying different wheels based on the environment/OS, in a
        # single requirements file.
        if install_req.link and install_req.link.is_wheel:
            wheel = Wheel(install_req.link.filename)
            tags = pep425tags.get_supported()
            if (self.check_supported_wheels and not wheel.supported(tags)):
                raise InstallationError(
                    "%s is not a supported wheel on this platform." %
                    wheel.filename)

        # This next bit is really a sanity check.
        assert install_req.is_direct == (parent_req_name is None), (
            "a direct req shouldn't have a parent and also, "
            "a non direct req should have a parent")

        # Unnamed requirements are scanned again and the requirement won't be
        # added as a dependency until after scanning.
        if not install_req.name:
            self.add_unnamed_requirement(install_req)
            return [install_req], None

        try:
            existing_req = self.get_requirement(install_req.name)
        except KeyError:
            existing_req = None

        has_conflicting_requirement = (
            parent_req_name is None and existing_req
            and not existing_req.constraint
            and existing_req.extras == install_req.extras
            and existing_req.req.specifier != install_req.req.specifier)
        if has_conflicting_requirement:
            raise InstallationError(
                "Double requirement given: %s (already in %s, name=%r)" %
                (install_req, existing_req, install_req.name))

        # When no existing requirement exists, add the requirement as a
        # dependency and it will be scanned again after.
        if not existing_req:
            self.add_named_requirement(install_req)
            # We'd want to rescan this requirement later
            return [install_req], install_req

        # Assume there's no need to scan, and that we've already
        # encountered this for scanning.
        if install_req.constraint or not existing_req.constraint:
            return [], existing_req

        does_not_satisfy_constraint = (
            install_req.link
            and not (existing_req.link
                     and install_req.link.path == existing_req.link.path))
        if does_not_satisfy_constraint:
            self.reqs_to_cleanup.append(install_req)
            raise InstallationError(
                "Could not satisfy constraints for '%s': "
                "installation from path or url cannot be "
                "constrained to a version" % install_req.name, )
        # If we're now installing a constraint, mark the existing
        # object for real installation.
        existing_req.constraint = False
        existing_req.extras = tuple(
            sorted(set(existing_req.extras) | set(install_req.extras)))
        logger.debug(
            "Setting %s extras to: %s",
            existing_req,
            existing_req.extras,
        )
        # Return the existing requirement for addition to the parent and
        # scanning again.
        return [existing_req], existing_req
Esempio n. 12
0
 def supported(self, tags=None):
     """Is this wheel supported on this system?"""
     if tags is None:  # for mock
         tags = pep425tags.get_supported()
     return bool(set(tags).intersection(self.file_tags))
    def __init__(self, find_links, index_urls, allow_all_prereleases=False,
                 trusted_hosts=None, process_dependency_links=False,
                 session=None, format_control=None, platform=None,
                 versions=None, abi=None, implementation=None,
                 prefer_binary=False):
        """Create a PackageFinder.

        :param format_control: A FormatControl object or None. Used to control
            the selection of source packages / binary packages when consulting
            the index and links.
        :param platform: A string or None. If None, searches for packages
            that are supported by the current system. Otherwise, will find
            packages that can be built on the platform passed in. These
            packages will only be downloaded for distribution: they will
            not be built locally.
        :param versions: A list of strings or None. This is passed directly
            to pep425tags.py in the get_supported() method.
        :param abi: A string or None. This is passed directly
            to pep425tags.py in the get_supported() method.
        :param implementation: A string or None. This is passed directly
            to pep425tags.py in the get_supported() method.
        """
        if session is None:
            raise TypeError(
                "PackageFinder() missing object-oriented required keyword argument: "
                "'session'"
            )

        # Build find_links. If an argument starts with ~, it may be
        # a local file relative to a home directory. So try normalizing
        # it and if it exists, use the normalized version.
        # This is deliberately conservative - it might be fine just to
        # blindly normalize anything starting with a ~...
        self.find_links = []
        for link in find_links:
            if link.startswith('~'):
                new_link = normalize_path(link)
                if os.path.exists(new_link):
                    link = new_link
            self.find_links.append(link)

        self.index_urls = index_urls
        self.dependency_links = []

        # These are boring links that have already been logged somehow:
        self.logged_links = set()

        self.format_control = format_control or FormatControl(set(), set())

        # Domains that we won't emit warnings for when not using HTTPS
        self.secure_origins = [
            ("*", host, "*")
            for host in (trusted_hosts if trusted_hosts else [])
        ]

        # Do we want to allow _all_ pre-releases?
        self.allow_all_prereleases = allow_all_prereleases

        # Do we process dependency links?
        self.process_dependency_links = process_dependency_links

        # The Session we'll use to make requests
        self.session = session

        # The valid tags to check potential found wheel candidates against
        self.valid_tags = get_supported(
            versions=versions,
            platform=platform,
            abi=abi,
            impl=implementation,
        )

        # Do we prefer old, but valid, binary dist over new source dist
        self.prefer_binary = prefer_binary

        # If we don't have TLS enabled, then WARN if anyplace we're looking
        # relies on TLS.
        if not HAS_TLS:
            for link in itertools.chain(self.index_urls, self.find_links):
                parsed = urllib_parse.urlparse(link)
                if parsed.scheme == "https":
                    logger.warning(
                        "pip is configured with locations that require "
                        "TLS/SSL, however the ssl module in Python is not "
                        "available."
                    )
                    break