Example #1
0
    def populate_requirement_set(requirement_set, args, options, finder,
                                 session, name, wheel_cache):
        """
        Marshal cmd line args into a requirement set.
        """
        # NOTE: As a side-effect, options.require_hashes and
        #       requirement_set.require_hashes may be updated

        for filename in options.constraints:
            for req_to_add in parse_requirements(
                    filename,
                    constraint=True, finder=finder, options=options,
                    session=session, wheel_cache=wheel_cache):
                req_to_add.is_direct = True
                requirement_set.add_requirement(req_to_add)

        for req in args:
            req_to_add = InstallRequirement.from_line(
                req, None, isolated=options.isolated_mode,
                wheel_cache=wheel_cache
            )
            req_to_add.is_direct = True
            requirement_set.add_requirement(req_to_add)

        for req in options.editables:
            req_to_add = InstallRequirement.from_editable(
                req,
                isolated=options.isolated_mode,
                wheel_cache=wheel_cache
            )
            req_to_add.is_direct = True
            requirement_set.add_requirement(req_to_add)

        for filename in options.requirements:
            for req_to_add in parse_requirements(
                    filename,
                    finder=finder, options=options, session=session,
                    wheel_cache=wheel_cache):
                req_to_add.is_direct = True
                requirement_set.add_requirement(req_to_add)
        # If --require-hashes was a line in a requirements file, tell
        # RequirementSet about it:
        requirement_set.require_hashes = options.require_hashes

        if not (args or options.editables or options.requirements):
            opts = {'name': name}
            if options.find_links:
                raise CommandError(
                    'You must give at least one requirement to %(name)s '
                    '(maybe you meant "pip %(name)s %(links)s"?)' %
                    dict(opts, links=' '.join(options.find_links)))
            else:
                raise CommandError(
                    'You must give at least one requirement to %(name)s '
                    '(see "pip help %(name)s")' % opts)
Example #2
0
def install_req_from_editable(
    editable_req: str,
    comes_from: Optional[Union[InstallRequirement, str]] = None,
    use_pep517: Optional[bool] = None,
    isolated: bool = False,
    options: Optional[Dict[str, Any]] = None,
    constraint: bool = False,
    user_supplied: bool = False,
    permit_editable_wheels: bool = False,
) -> InstallRequirement:

    parts = parse_req_from_editable(editable_req)

    return InstallRequirement(
        parts.requirement,
        comes_from=comes_from,
        user_supplied=user_supplied,
        editable=True,
        permit_editable_wheels=permit_editable_wheels,
        link=parts.link,
        constraint=constraint,
        use_pep517=use_pep517,
        isolated=isolated,
        install_options=options.get("install_options", []) if options else [],
        global_options=options.get("global_options", []) if options else [],
        hash_options=options.get("hashes", {}) if options else {},
        extras=parts.extras,
    )
Example #3
0
    def prepare_linked_requirement(
            self,
            req: InstallRequirement,
            parallel_builds: bool = False) -> BaseDistribution:
        """Prepare a requirement to be obtained from req.link."""
        assert req.link
        link = req.link
        self._log_preparing_link(req)
        with indent_log():
            # Check if the relevant file is already available
            # in the download directory
            file_path = None
            if self.download_dir is not None and link.is_wheel:
                hashes = self._get_linked_req_hashes(req)
                file_path = _check_download_dir(req.link, self.download_dir,
                                                hashes)

            if file_path is not None:
                # The file is already available, so mark it as downloaded
                self._downloaded[req.link.url] = file_path
            else:
                # The file is not available, attempt to fetch only metadata
                wheel_dist = self._fetch_metadata_using_lazy_wheel(link)
                if wheel_dist is not None:
                    req.needs_more_preparation = True
                    return wheel_dist

            # None of the optimizations worked, fully prepare the requirement
            return self._prepare_linked_requirement(req, parallel_builds)
def install_req_from_editable(
        editable_req,  # type: str
        comes_from=None,  # type: Optional[str]
        use_pep517=None,  # type: Optional[bool]
        isolated=False,  # type: bool
        options=None,  # type: Optional[Dict[str, Any]]
        wheel_cache=None,  # type: Optional[WheelCache]
        constraint=False  # type: bool
):
    # type: (...) -> InstallRequirement

    parts = parse_req_from_editable(editable_req)

    source_dir = parts.link.file_path if parts.link.scheme == 'file' else None

    return InstallRequirement(
        parts.requirement,
        comes_from,
        source_dir=source_dir,
        editable=True,
        link=parts.link,
        constraint=constraint,
        use_pep517=use_pep517,
        isolated=isolated,
        options=options if options else {},
        wheel_cache=wheel_cache,
        extras=parts.extras,
    )
Example #5
0
def make_test_install_req(base_name=None):
    """
    Return an InstallRequirement object for testing purposes.
    """
    if base_name is None:
        base_name = 'pendulum-2.0.4'

    req = Requirement('pendulum')
    link_url = (
        'https://files.pythonhosted.org/packages/aa/{base_name}.tar.gz'
        '#sha256=cf535d36c063575d4752af36df928882b2e0e31541b4482c97d637527'
        '85f9fcb'
    ).format(base_name=base_name)
    link = Link(
        url=link_url,
        comes_from='https://pypi.org/simple/pendulum/',
        requires_python='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*',
    )
    req = InstallRequirement(
        req=req,
        comes_from=None,
        constraint=False,
        editable=False,
        link=link,
        source_dir='/tmp/pip-install-9py5m2z1/pendulum',
    )

    return req
Example #6
0
def test_should_use_ephemeral_cache__disallow_binaries_and_vcs_checkout(
    disallow_binaries,
    expected,
):
    """
    Test that disallowing binaries (e.g. from passing --global-option)
    causes should_use_ephemeral_cache() to return None for VCS checkouts.
    """
    req = Requirement('pendulum')
    link = Link(url='git+https://git.example.com/pendulum.git')
    req = InstallRequirement(
        req=req,
        comes_from=None,
        constraint=False,
        editable=False,
        link=link,
        source_dir='/tmp/pip-install-9py5m2z1/pendulum',
    )
    assert not req.is_wheel
    assert req.link.is_vcs

    check_binary_allowed = Mock(return_value=not disallow_binaries)

    # The cache_available value doesn't matter for this test.
    ephem_cache = wheel.should_use_ephemeral_cache(
        req,
        should_unpack=True,
        cache_available=True,
        check_binary_allowed=check_binary_allowed,
    )
    assert ephem_cache is expected
Example #7
0
 def test_yield_line_requirement_with_spaces_in_specifier(self):
     line = 'SomeProject >= 2'
     filename = 'filename'
     comes_from = '-r %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_line(line, comes_from=comes_from)
     assert repr(list(process_line(line, filename, 1))[0]) == repr(req)
     assert str(req.req.specifier) == '>=2'
Example #8
0
 def test_yield_editable_requirement(self):
     url = 'git+https://url#egg=SomeProject'
     line = '-e %s' % url
     filename = 'filename'
     comes_from = '-r %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_editable(url, comes_from=comes_from)
     assert repr(list(process_line(line, filename, 1))[0]) == repr(req)
Example #9
0
def install_req_from_editable(
    editable_req,  # type: str
    comes_from=None,  # type: Optional[str]
    use_pep517=None,  # type: Optional[bool]
    isolated=False,  # type: bool
    options=None,  # type: Optional[Dict[str, Any]]
    wheel_cache=None,  # type: Optional[WheelCache]
    constraint=False  # type: bool
):
    # type: (...) -> InstallRequirement
    name, url, extras_override = parse_editable(editable_req)
    if url.startswith('file:'):
        source_dir = url_to_path(url)
    else:
        source_dir = None

    if name is not None:
        try:
            req = Requirement(name)
        except InvalidRequirement:
            raise InstallationError("Invalid requirement: '%s'" % name)
    else:
        req = None
    return InstallRequirement(
        req, comes_from, source_dir=source_dir,
        editable=True,
        link=Link(url),
        constraint=constraint,
        use_pep517=use_pep517,
        isolated=isolated,
        options=options if options else {},
        wheel_cache=wheel_cache,
        extras=extras_override or (),
    )
Example #10
0
def install_req_from_req_string(
    req_string,  # type: str
    comes_from=None,  # type: Optional[InstallRequirement]
    isolated=False,  # type: bool
    wheel_cache=None,  # type: Optional[WheelCache]
    use_pep517=None  # type: Optional[bool]
):
    # type: (...) -> InstallRequirement
    try:
        req = Requirement(req_string)
    except InvalidRequirement:
        raise InstallationError("Invalid requirement: '%s'" % req)

    domains_not_allowed = [
        PyPI.file_storage_domain,
        TestPyPI.file_storage_domain,
    ]
    if req.url and comes_from.link.netloc in domains_not_allowed:
        # Explicitly disallow pypi packages that depend on external urls
        raise InstallationError(
            "Packages installed from PyPI cannot depend on packages "
            "which are not also hosted on PyPI.\n"
            "%s depends on %s " % (comes_from.name, req)
        )

    return InstallRequirement(
        req, comes_from, isolated=isolated, wheel_cache=wheel_cache,
        use_pep517=use_pep517
    )
Example #11
0
def test_should_use_ephemeral_cache__disallow_binaries_and_vcs_checkout(
    disallow_binaries,
    expected,
):
    """
    Test that disallowing binaries (e.g. from passing --global-option)
    causes should_use_ephemeral_cache() to return None for VCS checkouts.
    """
    req = Requirement('pendulum')
    # Passing a VCS url causes link.is_artifact to return False.
    link = Link(url='git+https://git.example.com/pendulum.git')
    req = InstallRequirement(
        req=req,
        comes_from=None,
        constraint=False,
        editable=False,
        link=link,
        source_dir='/tmp/pip-install-9py5m2z1/pendulum',
    )
    assert not req.is_wheel
    assert not req.link.is_artifact

    format_control = FormatControl()
    if disallow_binaries:
        format_control.disallow_binaries()

    # The cache_available value doesn't matter for this test.
    ephem_cache = wheel.should_use_ephemeral_cache(
        req,
        format_control=format_control,
        autobuilding=True,
        cache_available=True,
    )
    assert ephem_cache is expected
Example #12
0
def install_req_from_req_string(
        req_string,  # type: str
        comes_from=None,  # type: Optional[InstallRequirement]
        isolated=False,  # type: bool
        use_pep517=None,  # type: Optional[bool]
        user_supplied=False,  # type: bool
):
    # type: (...) -> InstallRequirement
    try:
        req = Requirement(req_string)
    except InvalidRequirement:
        raise InstallationError(f"Invalid requirement: '{req_string}'")

    domains_not_allowed = [
        PyPI.file_storage_domain,
        TestPyPI.file_storage_domain,
    ]
    if (req.url and comes_from and comes_from.link
            and comes_from.link.netloc in domains_not_allowed):
        # Explicitly disallow pypi packages that depend on external urls
        raise InstallationError(
            "Packages installed from PyPI cannot depend on packages "
            "which are not also hosted on PyPI.\n"
            "{} depends on {} ".format(comes_from.name, req))

    return InstallRequirement(
        req,
        comes_from,
        isolated=isolated,
        use_pep517=use_pep517,
        user_supplied=user_supplied,
    )
Example #13
0
def install_req_from_editable(
        editable_req,  # type: str
        comes_from=None,  # type: Optional[Union[InstallRequirement, str]]
        use_pep517=None,  # type: Optional[bool]
        isolated=False,  # type: bool
        options=None,  # type: Optional[Dict[str, Any]]
        constraint=False,  # type: bool
        user_supplied=False,  # type: bool
):
    # type: (...) -> InstallRequirement

    parts = parse_req_from_editable(editable_req)

    return InstallRequirement(
        parts.requirement,
        comes_from=comes_from,
        user_supplied=user_supplied,
        editable=True,
        link=parts.link,
        constraint=constraint,
        use_pep517=use_pep517,
        isolated=isolated,
        install_options=options.get("install_options", []) if options else [],
        global_options=options.get("global_options", []) if options else [],
        hash_options=options.get("hashes", {}) if options else {},
        extras=parts.extras,
    )
Example #14
0
def install_req_from_line(
        name,  # type: str
        comes_from=None,  # type: Optional[Union[str, InstallRequirement]]
        use_pep517=None,  # type: Optional[bool]
        isolated=False,  # type: bool
        options=None,  # type: Optional[Dict[str, Any]]
        constraint=False,  # type: bool
        line_source=None,  # type: Optional[str]
        user_supplied=False,  # type: bool
):
    # type: (...) -> InstallRequirement
    """Creates an InstallRequirement from a name, which might be a
    requirement, directory containing 'setup.py', filename, or URL.

    :param line_source: An optional string describing where the line is from,
        for logging purposes in case of an error.
    """
    parts = parse_req_from_line(name, line_source)

    return InstallRequirement(
        parts.requirement,
        comes_from,
        link=parts.link,
        markers=parts.markers,
        use_pep517=use_pep517,
        isolated=isolated,
        install_options=options.get("install_options", []) if options else [],
        global_options=options.get("global_options", []) if options else [],
        hash_options=options.get("hashes", {}) if options else {},
        constraint=constraint,
        extras=parts.extras,
        user_supplied=user_supplied,
    )
 def test_yield_line_requirement_with_spaces_in_specifier(self):
     line = 'SomeProject >= 2'
     filename = 'filename'
     comes_from = '-r %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_line(line, comes_from=comes_from)
     assert repr(list(process_line(line, filename, 1))[0]) == repr(req)
     assert str(req.req.specifier) == '>=2'
 def test_yield_editable_requirement(self):
     url = 'git+https://url#egg=SomeProject'
     line = '-e %s' % url
     filename = 'filename'
     comes_from = '-r %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_editable(url, comes_from=comes_from)
     assert repr(list(process_line(line, filename, 1))[0]) == repr(req)
Example #17
0
    def test_install_req_from_string_with_comes_from_without_link(
            self) -> None:
        """
        Test to make sure that install_req_from_string succeeds
        when called with URL (PEP 508) and comes_from
        does not have a link.
        """
        # Test with a PEP 508 url install string:
        wheel_url = ("https://download.pytorch.org/whl/cu90/"
                     "torch-1.0.0-cp36-cp36m-win_amd64.whl")
        install_str = "torch@ " + wheel_url

        # Dummy numpy "comes_from" requirement without link:
        comes_from = InstallRequirement(Requirement("numpy>=1.15.0"),
                                        comes_from=None)

        # Attempt install from install string comes:
        install_req = install_req_from_req_string(install_str,
                                                  comes_from=comes_from)

        assert isinstance(install_req, InstallRequirement)
        assert isinstance(install_req.comes_from, InstallRequirement)
        assert install_req.comes_from.link is None
        assert install_req.link is not None
        assert install_req.link.url == wheel_url
        assert install_req.req is not None
        assert install_req.req.url == wheel_url
        assert install_req.is_wheel
Example #18
0
def install_req_from_editable(
    editable_req, comes_from=None, isolated=False, options=None,
    wheel_cache=None, constraint=False
):
    name, url, extras_override = parse_editable(editable_req)
    if url.startswith('file:'):
        source_dir = url_to_path(url)
    else:
        source_dir = None

    if name is not None:
        try:
            req = Requirement(name)
        except InvalidRequirement:
            raise InstallationError("Invalid requirement: '%s'" % name)
    else:
        req = None
    return InstallRequirement(
        req, comes_from, source_dir=source_dir,
        editable=True,
        link=Link(url),
        constraint=constraint,
        isolated=isolated,
        options=options if options else {},
        wheel_cache=wheel_cache,
        extras=extras_override or (),
    )
Example #19
0
 def _make_requirement_from_install_req(
         self, ireq: InstallRequirement,
         requested_extras: Iterable[str]) -> Optional[Requirement]:
     if not ireq.match_markers(requested_extras):
         logger.info(
             "Ignoring %s: markers '%s' don't match your environment",
             ireq.name,
             ireq.markers,
         )
         return None
     if not ireq.link:
         return SpecifierRequirement(ireq)
     self._fail_if_link_is_unsupported_wheel(ireq.link)
     cand = self._make_candidate_from_link(
         ireq.link,
         extras=frozenset(ireq.extras),
         template=ireq,
         name=canonicalize_name(ireq.name) if ireq.name else None,
         version=None,
     )
     if cand is None:
         # There's no way we can satisfy a URL requirement if the underlying
         # candidate fails to build. An unnamed URL must be user-supplied, so
         # we fail eagerly. If the URL is named, an unsatisfiable requirement
         # can make the resolver do the right thing, either backtrack (and
         # maybe find some other requirement that's buildable) or raise a
         # ResolutionImpossible eventually.
         if not ireq.name:
             raise self._build_failures[ireq.link]
         return UnsatisfiableRequirement(canonicalize_name(ireq.name))
     return self.make_requirement_from_candidate(cand)
 def test_tmp_build_directory(self):
     # when req is None, we can produce a temporary directory
     # Make sure we're handling it correctly with real path.
     requirement = InstallRequirement(None, None)
     tmp_dir = tempfile.mkdtemp('-build', 'pip-')
     tmp_build_dir = requirement.build_location(tmp_dir)
     assert (
         os.path.dirname(tmp_build_dir) ==
         os.path.realpath(os.path.dirname(tmp_dir))
     )
     # are we on a system where /tmp is a symlink
     if os.path.realpath(tmp_dir) != os.path.abspath(tmp_dir):
         assert os.path.dirname(tmp_build_dir) != os.path.dirname(tmp_dir)
     else:
         assert os.path.dirname(tmp_build_dir) == os.path.dirname(tmp_dir)
     os.rmdir(tmp_dir)
     assert not os.path.exists(tmp_dir)
Example #21
0
    def _get_dist_for(self, req: InstallRequirement) -> Distribution:
        """Takes a InstallRequirement and returns a single AbstractDist \
        representing a prepared variant of the same.
        """
        if req.editable:
            return self.preparer.prepare_editable_requirement(req)

        # satisfied_by is only evaluated by calling _check_skip_installed,
        # so it must be None here.
        assert req.satisfied_by is None
        skip_reason = self._check_skip_installed(req)

        if req.satisfied_by:
            return self.preparer.prepare_installed_requirement(req, skip_reason)

        # We eagerly populate the link, since that's our "legacy" behavior.
        self._populate_link(req)
        dist = self.preparer.prepare_linked_requirement(req)

        # NOTE
        # The following portion is for determining if a certain package is
        # going to be re-installed/upgraded or not and reporting to the user.
        # This should probably get cleaned up in a future refactor.

        # req.req is only avail after unpack for URL
        # pkgs repeat check_if_exists to uninstall-on-upgrade
        # (#14)
        if not self.ignore_installed:
            req.check_if_exists(self.use_user_site)

        if req.satisfied_by:
            should_modify = (
                self.upgrade_strategy != "to-satisfy-only"
                or self.force_reinstall
                or self.ignore_installed
                or req.link.scheme == "file"
            )
            if should_modify:
                self._set_req_to_reinstall(req)
            else:
                logger.info(
                    "Requirement already satisfied (use --upgrade to upgrade): %s",
                    req,
                )
        return dist
Example #22
0
    def prepare_editable_requirement(
        self,
        req: InstallRequirement,
    ) -> BaseDistribution:
        """Prepare an editable requirement."""
        assert req.editable, "cannot prepare a non-editable req as editable"

        logger.info("Obtaining %s", req)

        with indent_log():
            if self.require_hashes:
                raise InstallationError(
                    "The editable requirement {} cannot be installed when "
                    "requiring hashes, because there is no single file to "
                    "hash.".format(req))
            req.ensure_has_source_dir(self.src_dir)
            req.update_editable()
            assert req.source_dir
            req.download_info = direct_url_for_editable(
                req.unpacked_source_directory)

            dist = _get_prepared_distribution(
                req,
                self.build_tracker,
                self.finder,
                self.build_isolation,
                self.check_build_deps,
            )

            req.check_if_exists(self.use_user_site)

        return dist
Example #23
0
 def test_yield_line_constraint(self):
     line = 'SomeProject'
     filename = 'filename'
     comes_from = '-c %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_line(
         line, comes_from=comes_from, constraint=True)
     found_req = list(process_line(line, filename, 1, constraint=True))[0]
     assert repr(found_req) == repr(req)
     assert found_req.constraint is True
Example #24
0
 def test_yield_line_constraint(self):
     line = 'SomeProject'
     filename = 'filename'
     comes_from = '-c %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_line(
         line, comes_from=comes_from, constraint=True)
     found_req = list(process_line(line, filename, 1, constraint=True))[0]
     assert repr(found_req) == repr(req)
     assert found_req.constraint is True
Example #25
0
 def __and__(self, other: InstallRequirement) -> "Constraint":
     if not isinstance(other, InstallRequirement):
         return NotImplemented
     specifier = self.specifier & other.specifier
     hashes = self.hashes & other.hashes(trust_internet=False)
     links = self.links
     if other.link:
         links = links.union([other.link])
     return Constraint(specifier, hashes, links)
Example #26
0
 def test_yield_editable_constraint(self):
     url = 'git+https://url#egg=SomeProject'
     line = '-e %s' % url
     filename = 'filename'
     comes_from = '-c %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_editable(
         url, comes_from=comes_from, constraint=True)
     found_req = list(process_line(line, filename, 1, constraint=True))[0]
     assert repr(found_req) == repr(req)
     assert found_req.constraint is True
Example #27
0
 def test_yield_editable_constraint(self):
     url = 'git+https://url#egg=SomeProject'
     line = '-e %s' % url
     filename = 'filename'
     comes_from = '-c %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_editable(
         url, comes_from=comes_from, constraint=True)
     found_req = list(process_line(line, filename, 1, constraint=True))[0]
     assert repr(found_req) == repr(req)
     assert found_req.constraint is True
Example #28
0
 def test_tmp_build_directory(self) -> None:
     # when req is None, we can produce a temporary directory
     # Make sure we're handling it correctly with real path.
     requirement = InstallRequirement(None, None)
     tmp_dir = tempfile.mkdtemp("-build", "pip-")
     tmp_build_dir = requirement.ensure_build_location(
         tmp_dir,
         autodelete=False,
         parallel_builds=False,
     )
     assert os.path.dirname(tmp_build_dir) == os.path.realpath(
         os.path.dirname(tmp_dir))
     # are we on a system where /tmp is a symlink
     if os.path.realpath(tmp_dir) != os.path.abspath(tmp_dir):
         assert os.path.dirname(tmp_build_dir) != os.path.dirname(tmp_dir)
     else:
         assert os.path.dirname(tmp_build_dir) == os.path.dirname(tmp_dir)
     os.rmdir(tmp_dir)
     assert not os.path.exists(tmp_dir)
Example #29
0
def test_rejection_for_location_requirement_options():
    install_options = []

    bad_named_req_options = ["--home=/wow"]
    bad_named_req = InstallRequirement(Requirement("hello"),
                                       "requirements.txt",
                                       install_options=bad_named_req_options)

    bad_unnamed_req_options = ["--install-lib=/lib"]
    bad_unnamed_req = InstallRequirement(
        None, "requirements2.txt", install_options=bad_unnamed_req_options)

    with pytest.raises(CommandError) as e:
        reject_location_related_install_options(
            [bad_named_req, bad_unnamed_req], install_options)

    assert (
        "['--install-lib'] from <InstallRequirement> (from requirements2.txt)"
        in str(e.value))
    assert "['--home'] from hello (from requirements.txt)" in str(e.value)
Example #30
0
 def add_req(subreq, extras_requested):
     sub_install_req = InstallRequirement.from_req(
         str(subreq),
         req_to_install,
         isolated=self.isolated,
         wheel_cache=self.wheel_cache,
     )
     more_reqs.extend(
         requirement_set.add_requirement(
             sub_install_req,
             req_to_install.name,
             extras_requested=extras_requested))
Example #31
0
    def test_nested_constraints_file(self, monkeypatch):
        line = '-c another_file'
        req = InstallRequirement.from_line('SomeProject')
        import pip._internal.req.req_file

        def stub_parse_requirements(req_url, finder, comes_from, options,
                                    session, wheel_cache, constraint):
            return [(req, constraint)]
        parse_requirements_stub = stub(call=stub_parse_requirements)
        monkeypatch.setattr(pip._internal.req.req_file, 'parse_requirements',
                            parse_requirements_stub.call)
        assert list(process_line(line, 'filename', 1)) == [(req, True)]
Example #32
0
    def test_nested_constraints_file(self, monkeypatch):
        line = '-c another_file'
        req = InstallRequirement.from_line('SomeProject')
        import pip._internal.req.req_file

        def stub_parse_requirements(req_url, finder, comes_from, options,
                                    session, wheel_cache, constraint):
            return [(req, constraint)]
        parse_requirements_stub = stub(call=stub_parse_requirements)
        monkeypatch.setattr(pip._internal.req.req_file, 'parse_requirements',
                            parse_requirements_stub.call)
        assert list(process_line(line, 'filename', 1)) == [(req, True)]
Example #33
0
    def prepare_editable_requirement(
        self,
        req: InstallRequirement,
    ) -> Distribution:
        """Prepare an editable requirement
        """
        assert req.editable, "cannot prepare a non-editable req as editable"

        logger.info('Obtaining %s', req)

        with indent_log():
            if self.require_hashes:
                raise InstallationError(
                    'The editable requirement {} cannot be installed when '
                    'requiring hashes, because there is no single file to '
                    'hash.'.format(req)
                )
            req.ensure_has_source_dir(self.src_dir)
            req.update_editable()

            dist = _get_prepared_distribution(
                req, self.req_tracker, self.finder, self.build_isolation,
            )

            req.check_if_exists(self.use_user_site)

        return dist
Example #34
0
 def add_req(subreq, extras_requested):
     sub_install_req = InstallRequirement.from_req(
         str(subreq),
         req_to_install,
         isolated=self.isolated,
         wheel_cache=self.wheel_cache,
     )
     more_reqs.extend(
         requirement_set.add_requirement(
             sub_install_req, req_to_install.name,
             extras_requested=extras_requested
         )
     )
Example #35
0
def test_deprecation_notice_for_requirement_options(recwarn):
    install_options = []

    bad_named_req_options = ["--home=/wow"]
    bad_named_req = InstallRequirement(Requirement("hello"),
                                       "requirements.txt",
                                       install_options=bad_named_req_options)

    bad_unnamed_req_options = ["--install-lib=/lib"]
    bad_unnamed_req = InstallRequirement(
        None, "requirements2.txt", install_options=bad_unnamed_req_options)

    warn_deprecated_install_options([bad_named_req, bad_unnamed_req],
                                    install_options)

    assert len(recwarn) == 1
    message = recwarn[0].message.args[0]

    assert (
        "['--install-lib'] from <InstallRequirement> (from requirements2.txt)"
        in message)
    assert "['--home'] from hello (from requirements.txt)" in message
Example #36
0
def _should_build(
    req: InstallRequirement,
    need_wheel: bool,
    check_binary_allowed: BinaryAllowedPredicate,
) -> bool:
    """Return whether an InstallRequirement should be built into a wheel."""
    if req.constraint:
        # never build requirements that are merely constraints
        return False
    if req.is_wheel:
        if need_wheel:
            logger.info(
                "Skipping %s, due to already being wheel.",
                req.name,
            )
        return False

    if need_wheel:
        # i.e. pip wheel, not pip install
        return True

    # From this point, this concerns the pip install command only
    # (need_wheel=False).

    if not req.source_dir:
        return False

    if req.editable:
        # we only build PEP 660 editable requirements
        return req.supports_pyproject_editable()

    if req.use_pep517:
        return True

    if not check_binary_allowed(req):
        logger.info(
            "Skipping wheel build for %s, due to binaries being disabled for it.",
            req.name,
        )
        return False

    if not is_wheel_installed():
        # we don't build legacy requirements if wheel is not installed
        logger.info(
            "Using legacy 'setup.py install' for %s, "
            "since package 'wheel' is not installed.",
            req.name,
        )
        return False

    return True
    def test_forward_slash_results_in_a_link(self, tmpdir):
        install_dir = tmpdir / "foo" / "bar"

        # Just create a file for letting the logic work
        setup_py_path = install_dir / "setup.py"
        os.makedirs(str(install_dir))
        with open(setup_py_path, 'w') as f:
            f.write('')

        requirement = InstallRequirement.from_line(
            str(install_dir).replace(os.sep, os.altsep or os.sep)
        )

        assert requirement.link is not None
Example #38
0
File: wheel.py Project: oz123/pip
    def _install_build_reqs(self, reqs, prefix):
        # Local import to avoid circular import (wheel <-> req_install)
        from pip._internal.req.req_install import InstallRequirement
        from pip._internal.index import FormatControl
        # Ignore the --no-binary option when installing the build system, so
        # we don't recurse trying to build a self-hosting build system.
        finder = copy.copy(self.finder)
        finder.format_control = FormatControl(set(), set())
        urls = [finder.find_requirement(InstallRequirement.from_line(r),
                                        upgrade=False).url
                for r in reqs]

        args = [sys.executable, '-m', 'pip', 'install', '--ignore-installed',
                '--prefix', prefix] + list(urls)
        with open_spinner("Installing build dependencies") as spinner:
            call_subprocess(args, show_stdout=False, spinner=spinner)
Example #39
0
def _install_build_reqs(finder, prefix, build_requirements):
    # NOTE: What follows is not a very good thing.
    #       Eventually, this should move into the BuildEnvironment class and
    #       that should handle all the isolation and sub-process invocation.
    finder = copy(finder)
    finder.format_control = FormatControl(set(), set([":all:"]))
    urls = [
        finder.find_requirement(
            InstallRequirement.from_line(r), upgrade=False).url
        for r in build_requirements
    ]
    args = [
        sys.executable, '-m', 'pip', 'install', '--ignore-installed',
        '--no-user', '--prefix', prefix,
    ] + list(urls)

    with open_spinner("Installing build dependencies") as spinner:
        call_subprocess(args, show_stdout=False, spinner=spinner)
Example #40
0
 def add_req(subreq, extras_requested):
     sub_install_req = InstallRequirement.from_req(
         str(subreq),
         req_to_install,
         isolated=self.isolated,
         wheel_cache=self.wheel_cache,
     )
     parent_req_name = req_to_install.name
     to_scan_again, add_to_parent = requirement_set.add_requirement(
         sub_install_req,
         parent_req_name=parent_req_name,
         extras_requested=extras_requested,
     )
     if parent_req_name and add_to_parent:
         self._discovered_dependencies[parent_req_name].append(
             add_to_parent
         )
     more_reqs.extend(to_scan_again)
Example #41
0
 def test_yield_line_requirement(self):
     line = 'SomeProject'
     filename = 'filename'
     comes_from = '-r %s (line %s)' % (filename, 1)
     req = InstallRequirement.from_line(line, comes_from=comes_from)
     assert repr(list(process_line(line, filename, 1))[0]) == repr(req)
Example #42
0
def process_line(line, filename, line_number, finder=None, comes_from=None,
                 options=None, session=None, wheel_cache=None,
                 constraint=False):
    """Process a single requirements line; This can result in creating/yielding
    requirements, or updating the finder.

    For lines that contain requirements, the only options that have an effect
    are from SUPPORTED_OPTIONS_REQ, and they are scoped to the
    requirement. Other options from SUPPORTED_OPTIONS may be present, but are
    ignored.

    For lines that do not contain requirements, the only options that have an
    effect are from SUPPORTED_OPTIONS. Options from SUPPORTED_OPTIONS_REQ may
    be present, but are ignored. These lines may contain multiple options
    (although our docs imply only one is supported), and all our parsed and
    affect the finder.

    :param constraint: If True, parsing a constraints file.
    :param options: OptionParser options that we may update
    """
    parser = build_parser(line)
    defaults = parser.get_default_values()
    defaults.index_url = None
    if finder:
        # `finder.format_control` will be updated during parsing
        defaults.format_control = finder.format_control
    args_str, options_str = break_args_options(line)
    if sys.version_info < (2, 7, 3):
        # Prior to 2.7.3, shlex cannot deal with unicode entries
        options_str = options_str.encode('utf8')
    opts, _ = parser.parse_args(shlex.split(options_str), defaults)

    # preserve for the nested code path
    line_comes_from = '%s %s (line %s)' % (
        '-c' if constraint else '-r', filename, line_number)

    # yield a line requirement
    if args_str:
        isolated = options.isolated_mode if options else False
        if options:
            cmdoptions.check_install_build_global(options, opts)
        # get the options that apply to requirements
        req_options = {}
        for dest in SUPPORTED_OPTIONS_REQ_DEST:
            if dest in opts.__dict__ and opts.__dict__[dest]:
                req_options[dest] = opts.__dict__[dest]
        yield InstallRequirement.from_line(
            args_str, line_comes_from, constraint=constraint,
            isolated=isolated, options=req_options, wheel_cache=wheel_cache
        )

    # yield an editable requirement
    elif opts.editables:
        isolated = options.isolated_mode if options else False
        yield InstallRequirement.from_editable(
            opts.editables[0], comes_from=line_comes_from,
            constraint=constraint, isolated=isolated, wheel_cache=wheel_cache
        )

    # parse a nested requirements file
    elif opts.requirements or opts.constraints:
        if opts.requirements:
            req_path = opts.requirements[0]
            nested_constraint = False
        else:
            req_path = opts.constraints[0]
            nested_constraint = True
        # original file is over http
        if SCHEME_RE.search(filename):
            # do a url join so relative paths work
            req_path = urllib_parse.urljoin(filename, req_path)
        # original file and nested file are paths
        elif not SCHEME_RE.search(req_path):
            # do a join so relative paths work
            req_path = os.path.join(os.path.dirname(filename), req_path)
        # TODO: Why not use `comes_from='-r {} (line {})'` here as well?
        parser = parse_requirements(
            req_path, finder, comes_from, options, session,
            constraint=nested_constraint, wheel_cache=wheel_cache
        )
        for req in parser:
            yield req

    # percolate hash-checking option upward
    elif opts.require_hashes:
        options.require_hashes = opts.require_hashes

    # set finder options
    elif finder:
        if opts.index_url:
            finder.index_urls = [opts.index_url]
        if opts.no_index is True:
            finder.index_urls = []
        if opts.extra_index_urls:
            finder.index_urls.extend(opts.extra_index_urls)
        if opts.find_links:
            # FIXME: it would be nice to keep track of the source
            # of the find_links: support a find-links local path
            # relative to a requirements file.
            value = opts.find_links[0]
            req_dir = os.path.dirname(os.path.abspath(filename))
            relative_to_reqs_file = os.path.join(req_dir, value)
            if os.path.exists(relative_to_reqs_file):
                value = relative_to_reqs_file
            finder.find_links.append(value)
        if opts.pre:
            finder.allow_all_prereleases = True
        if opts.process_dependency_links:
            finder.process_dependency_links = True
        if opts.trusted_hosts:
            finder.secure_origins.extend(
                ("*", host, "*") for host in opts.trusted_hosts)
Example #43
0
    def populate_requirement_set(requirement_set, args, options, finder,
                                 session, name, wheel_cache):
        """
        Marshal cmd line args into a requirement set.
        """
        # NOTE: As a side-effect, options.require_hashes and
        #       requirement_set.require_hashes may be updated

        for filename in options.constraints:
            for req in parse_requirements(
                    filename,
                    constraint=True, finder=finder, options=options,
                    session=session, wheel_cache=wheel_cache):
                requirement_set.add_requirement(req)

        for req in args:
            requirement_set.add_requirement(
                InstallRequirement.from_line(
                    req, None, isolated=options.isolated_mode,
                    wheel_cache=wheel_cache
                )
            )

        for req in options.editables:
            requirement_set.add_requirement(
                InstallRequirement.from_editable(
                    req,
                    isolated=options.isolated_mode,
                    wheel_cache=wheel_cache
                )
            )

        for filename in options.requirements:
            for req in parse_requirements(
                    filename,
                    finder=finder, options=options, session=session,
                    wheel_cache=wheel_cache):
                requirement_set.add_requirement(req)
        # If --require-hashes was a line in a requirements file, tell
        # RequirementSet about it:
        requirement_set.require_hashes = options.require_hashes

        if not (args or options.editables or options.requirements):
            opts = {'name': name}
            if options.find_links:
                raise CommandError(
                    'You must give at least one requirement to %(name)s '
                    '(maybe you meant "pip %(name)s %(links)s"?)' %
                    dict(opts, links=' '.join(options.find_links)))
            else:
                raise CommandError(
                    'You must give at least one requirement to %(name)s '
                    '(see "pip help %(name)s")' % opts)

        # On Windows, any operation modifying pip should be run as:
        #     python -m pip ...
        # See https://github.com/pypa/pip/issues/1299 for more discussion
        should_show_use_python_msg = (
            WINDOWS and
            requirement_set.has_requirement('pip') and
            "pip" in os.path.basename(sys.argv[0])
        )
        if should_show_use_python_msg:
            new_command = [
                sys.executable, "-m", "pip"
            ] + sys.argv[1:]
            raise CommandError(
                'To modify pip, please run the following command:\n{}'
                .format(" ".join(new_command))
            )