Issue #2867: Accept --no/only-binary via pip.conf

This commit is contained in:
Robert Collins 2015-06-09 12:05:48 +12:00
parent 8e3eaec559
commit a66d3e2e8b
3 changed files with 64 additions and 20 deletions

View File

@ -3,6 +3,8 @@
* Allow constraining versions globally without having to know exactly what will
be installed by the pip command. :issue:`2731`.
* Accept --no-binary and --only-binary via pip.conf. :issue`2867`.
**7.0.3 (2015-06-01)**
* Fixed a regression where ``--no-cache-dir`` would raise an exception, fixes

View File

@ -100,13 +100,15 @@ class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
class UpdatingDefaultsHelpFormatter(PrettyHelpFormatter):
"""Custom help formatter for use in ConfigOptionParser that updates
the defaults before expanding them, allowing them to show up correctly
in the help listing"""
"""Custom help formatter for use in ConfigOptionParser.
This is updates the defaults before expanding them, allowing
them to show up correctly in the help listing.
"""
def expand_default(self, option):
if self.parser is not None:
self.parser.update_defaults(self.parser.defaults)
self.parser._update_defaults(self.parser.defaults)
return optparse.IndentedHelpFormatter.expand_default(self, option)
@ -193,7 +195,7 @@ class ConfigOptionParser(CustomOptionParser):
print("An error occurred during configuration: %s" % exc)
sys.exit(3)
def update_defaults(self, defaults):
def _update_defaults(self, defaults):
"""Updates the given defaults with values from the config files and
the environ. Does a little special handling for certain types of
options (lists)."""
@ -207,22 +209,43 @@ class ConfigOptionParser(CustomOptionParser):
# 2. environmental variables
if not self.isolated:
config.update(self.normalize_keys(self.get_environ_vars()))
# Accumulate complex default state.
self.values = optparse.Values(self.defaults)
late_eval = set()
# Then set the options with those values
for key, val in config.items():
option = self.get_option(key)
if option is not None:
# ignore empty values
if not val:
continue
if option.action in ('store_true', 'store_false', 'count'):
val = strtobool(val)
if option.action == 'append':
val = val.split()
val = [self.check_default(option, key, v) for v in val]
else:
val = self.check_default(option, key, val)
# ignore empty values
if not val:
continue
defaults[option.dest] = val
option = self.get_option(key)
# Ignore options not present in this parser. E.g. non-globals put
# in [global] by users that want them to apply to all applicable
# commands.
if option is None:
continue
if option.action in ('store_true', 'store_false', 'count'):
val = strtobool(val)
elif option.action == 'append':
val = val.split()
val = [self.check_default(option, key, v) for v in val]
elif option.action == 'callback':
late_eval.add(option.dest)
opt_str = option.get_opt_string()
val = option.convert_value(opt_str, val)
# From take_action
args = option.callback_args or ()
kwargs = option.callback_kwargs or {}
option.callback(option, opt_str, val, self, *args, **kwargs)
else:
val = self.check_default(option, key, val)
defaults[option.dest] = val
for key in late_eval:
defaults[key] = getattr(self.values, key)
self.values = None
return defaults
def normalize_keys(self, items):
@ -251,12 +274,12 @@ class ConfigOptionParser(CustomOptionParser):
def get_default_values(self):
"""Overridding to make updating the defaults after instantiation of
the option parser possible, update_defaults() does the dirty work."""
the option parser possible, _update_defaults() does the dirty work."""
if not self.process_default_values:
# Old, pre-Optik 1.5 behaviour.
return optparse.Values(self.defaults)
defaults = self.update_defaults(self.defaults.copy()) # ours
defaults = self._update_defaults(self.defaults.copy()) # ours
for option in self._get_all_options():
default = defaults.get(option.dest)
if isinstance(default, string_types):

View File

@ -196,3 +196,22 @@ def test_options_from_venv_config(script, virtualenv):
"DistributionNotFound: No matching distribution found for INITools"
in result.stdout
)
def test_install_no_binary_via_config_disables_cached_wheels(script, data):
script.pip('install', 'wheel')
config_file = tempfile.NamedTemporaryFile(mode='wt')
script.environ['PIP_CONFIG_FILE'] = config_file.name
config_file.write(textwrap.dedent("""\
[global]
no-binary = :all:
"""))
config_file.flush()
res = script.pip(
'install', '--no-index', '-f', data.find_links,
'upper', expect_stderr=True)
assert "Successfully installed upper-2.0" in str(res), str(res)
# No wheel building for upper, which was blacklisted
assert "Running setup.py bdist_wheel for upper" not in str(res), str(res)
# Must have used source, not a cached wheel to install upper.
assert "Running setup.py install for upper" in str(res), str(res)