Obey --require-hashes option in requirements files.

Removed the mention of "package index options" in the docs, because they don't all fit that category anymore. Not even --no-binary and --only-binary do; they're "install options".
This commit is contained in:
Erik Rose 2015-10-21 15:50:57 -04:00
parent 3af5ffa5ce
commit f38fc903f2
5 changed files with 32 additions and 4 deletions

View File

@ -101,7 +101,7 @@ and the newline following it is effectively ignored.
Comments are stripped *before* line continuations are processed. Comments are stripped *before* line continuations are processed.
Additionally, the following Package Index Options are supported: The following options are supported:
* :ref:`-i, --index-url <--index-url>` * :ref:`-i, --index-url <--index-url>`
* :ref:`--extra-index-url <--extra-index-url>` * :ref:`--extra-index-url <--extra-index-url>`
@ -109,6 +109,7 @@ Additionally, the following Package Index Options are supported:
* :ref:`-f, --find-links <--find-links>` * :ref:`-f, --find-links <--find-links>`
* :ref:`--no-binary <install_--no-binary>` * :ref:`--no-binary <install_--no-binary>`
* :ref:`--only-binary <install_--only-binary>` * :ref:`--only-binary <install_--only-binary>`
* :ref:`--require-hashes <--require-hashes>`
For example, to specify :ref:`--no-index <--no-index>` and 2 :ref:`--find-links <--find-links>` locations: For example, to specify :ref:`--no-index <--no-index>` and 2 :ref:`--find-links <--find-links>` locations:
@ -486,6 +487,8 @@ against any requirement not only checks that hash but also activates a global
* ``--egg`` is disallowed, because it delegates installation of dependencies * ``--egg`` is disallowed, because it delegates installation of dependencies
to setuptools, giving up pip's ability to enforce any of the above. to setuptools, giving up pip's ability to enforce any of the above.
.. _`--require-hashes`:
Hash-checking mode can be forced on with the ``--require-hashes`` command-line Hash-checking mode can be forced on with the ``--require-hashes`` command-line
option:: option::

View File

@ -280,6 +280,9 @@ class RequirementCommand(Command):
wheel_cache=wheel_cache): wheel_cache=wheel_cache):
found_req_in_file = True found_req_in_file = True
requirement_set.add_requirement(req) 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 found_req_in_file): if not (args or options.editables or found_req_in_file):
opts = {'name': name} opts = {'name': name}

View File

@ -46,6 +46,7 @@ SUPPORTED_OPTIONS = [
cmdoptions.pre, cmdoptions.pre,
cmdoptions.process_dependency_links, cmdoptions.process_dependency_links,
cmdoptions.trusted_host, cmdoptions.trusted_host,
cmdoptions.require_hashes,
] ]
# options to be passed to requirements # options to be passed to requirements
@ -123,6 +124,7 @@ def process_line(line, filename, line_number, finder=None, comes_from=None,
affect the finder. affect the finder.
:param constraint: If True, parsing a constraints file. :param constraint: If True, parsing a constraints file.
:param options: OptionParser options that we may update
""" """
parser = build_parser() parser = build_parser()
defaults = parser.get_default_values() defaults = parser.get_default_values()
@ -187,6 +189,10 @@ def process_line(line, filename, line_number, finder=None, comes_from=None,
for req in parser: for req in parser:
yield req yield req
# percolate hash-checking option upward
elif opts.require_hashes:
options.require_hashes = opts.require_hashes
# set finder options # set finder options
elif finder: elif finder:
if opts.allow_external: if opts.allow_external:

View File

@ -190,7 +190,7 @@ class RequirementSet(object):
wheel_download_dir = normalize_path(wheel_download_dir) wheel_download_dir = normalize_path(wheel_download_dir)
self.wheel_download_dir = wheel_download_dir self.wheel_download_dir = wheel_download_dir
self._wheel_cache = wheel_cache self._wheel_cache = wheel_cache
self._require_hashes = require_hashes self.require_hashes = require_hashes
# Maps from install_req -> dependencies_of_install_req # Maps from install_req -> dependencies_of_install_req
self._dependencies = defaultdict(list) self._dependencies = defaultdict(list)
@ -331,7 +331,7 @@ class RequirementSet(object):
# If any top-level requirement has a hash specified, enter # If any top-level requirement has a hash specified, enter
# hash-checking mode, which requires hashes from all. # hash-checking mode, which requires hashes from all.
root_reqs = self.unnamed_requirements + self.requirements.values() root_reqs = self.unnamed_requirements + self.requirements.values()
require_hashes = (self._require_hashes or require_hashes = (self.require_hashes or
any(req.has_hash_options for req in root_reqs)) any(req.has_hash_options for req in root_reqs))
if require_hashes and self.as_egg: if require_hashes and self.as_egg:
raise InstallationError( raise InstallationError(

View File

@ -6,6 +6,7 @@ import tempfile
import pytest import pytest
from mock import Mock, patch, mock_open from mock import Mock, patch, mock_open
from pip.commands.install import InstallCommand
from pip.exceptions import (PreviousBuildDirError, InvalidWheelFilename, from pip.exceptions import (PreviousBuildDirError, InvalidWheelFilename,
UnsupportedWheel) UnsupportedWheel)
from pip.download import path_to_url, PipSession from pip.download import path_to_url, PipSession
@ -16,7 +17,7 @@ from pip.req.req_file import process_line
from pip.req.req_install import parse_editable from pip.req.req_install import parse_editable
from pip.utils import read_text_file from pip.utils import read_text_file
from pip._vendor import pkg_resources from pip._vendor import pkg_resources
from tests.lib import assert_raises_regexp from tests.lib import assert_raises_regexp, requirements_file
class TestRequirementSet(object): class TestRequirementSet(object):
@ -125,6 +126,21 @@ class TestRequirementSet(object):
reqset.prepare_files, reqset.prepare_files,
finder) finder)
def test_missing_hash_with_require_hashes_in_reqs_file(self, data, tmpdir):
"""--require-hashes in a requirements file should make its way to the
RequirementSet.
"""
req_set = self.basic_reqset(require_hashes=False)
session = PipSession()
finder = PackageFinder([data.find_links], [], session=session)
command = InstallCommand()
with requirements_file('--require-hashes', tmpdir) as reqs_file:
options, args = command.parse_args(['-r', reqs_file])
command.populate_requirement_set(
req_set, args, options, finder, session, command.name,
wheel_cache=None)
assert req_set.require_hashes
def test_unsupported_hashes(self, data): def test_unsupported_hashes(self, data):
"""VCS and dir links should raise errors when --require-hashes is """VCS and dir links should raise errors when --require-hashes is
on. on.