Closes issue #17732: ignore install-directory specific options in

distutils.cfg when a venv is active.
This commit is contained in:
Georg Brandl 2013-05-12 12:36:07 +02:00
parent b3bd624a55
commit 521ed52131
5 changed files with 87 additions and 3 deletions

View File

@ -645,6 +645,11 @@ environment variables, such as Mac OS 9, the configuration variables supplied by
the Distutils are the only ones you can use.) See section :ref:`inst-config-files`
for details.
.. note:: When a :ref:`virtual environment <venv-def>` is activated, any options
that change the installation path will be ignored from all distutils configuration
files to prevent inadvertently installing projects outside of the virtual
environment.
.. XXX need some Windows examples---when would custom installation schemes be
needed on those platforms?

View File

@ -57,6 +57,10 @@ Creating virtual environments
:attr:`sys.exec_prefix` is the same as :attr:`sys.base_exec_prefix` (they
all point to a non-venv Python installation).
When a venv is active, any options that change the installation path will be
ignored from all distutils configuration files to prevent projects being
inadvertently installed outside of the virtual environment.
API
---

View File

@ -343,6 +343,18 @@ Common commands: (see '--help-commands' for more)
def parse_config_files(self, filenames=None):
from configparser import ConfigParser
# Ignore install directory options if we have a venv
if sys.prefix != sys.base_prefix:
ignore_options = [
'install-base', 'install-platbase', 'install-lib',
'install-platlib', 'install-purelib', 'install-headers',
'install-scripts', 'install-data', 'prefix', 'exec-prefix',
'home', 'user', 'root']
else:
ignore_options = []
ignore_options = frozenset(ignore_options)
if filenames is None:
filenames = self.find_config_files()
@ -359,7 +371,7 @@ Common commands: (see '--help-commands' for more)
opt_dict = self.get_option_dict(section)
for opt in options:
if opt != '__name__':
if opt != '__name__' and opt not in ignore_options:
val = parser.get(section,opt)
opt = opt.replace('-', '_')
opt_dict[opt] = (filename, val)

View File

@ -6,6 +6,8 @@ import unittest
import warnings
import textwrap
from unittest import mock
from distutils.dist import Distribution, fix_help_options
from distutils.cmd import Command
@ -18,7 +20,7 @@ class test_dist(Command):
user_options = [
("sample-option=", "S", "help text"),
]
]
def initialize_options(self):
self.sample_option = None
@ -77,6 +79,64 @@ class DistributionTestCase(support.LoggingSilencer,
self.assertIsInstance(cmd, test_dist)
self.assertEqual(cmd.sample_option, "sometext")
def test_venv_install_options(self):
sys.argv.append("install")
self.addCleanup(os.unlink, TESTFN)
fakepath = '/somedir'
with open(TESTFN, "w") as f:
print(("[install]\n"
"install-base = {0}\n"
"install-platbase = {0}\n"
"install-lib = {0}\n"
"install-platlib = {0}\n"
"install-purelib = {0}\n"
"install-headers = {0}\n"
"install-scripts = {0}\n"
"install-data = {0}\n"
"prefix = {0}\n"
"exec-prefix = {0}\n"
"home = {0}\n"
"user = {0}\n"
"root = {0}").format(fakepath), file=f)
# Base case: Not in a Virtual Environment
with mock.patch.multiple(sys, prefix='/a', base_prefix='/a') as values:
d = self.create_distribution([TESTFN])
option_tuple = (TESTFN, fakepath)
result_dict = {
'install_base': option_tuple,
'install_platbase': option_tuple,
'install_lib': option_tuple,
'install_platlib': option_tuple,
'install_purelib': option_tuple,
'install_headers': option_tuple,
'install_scripts': option_tuple,
'install_data': option_tuple,
'prefix': option_tuple,
'exec_prefix': option_tuple,
'home': option_tuple,
'user': option_tuple,
'root': option_tuple,
}
self.assertEqual(
sorted(d.command_options.get('install').keys()),
sorted(result_dict.keys()))
for (key, value) in d.command_options.get('install').items():
self.assertEqual(value, result_dict[key])
# Test case: In a Virtual Environment
with mock.patch.multiple(sys, prefix='/a', base_prefix='/b') as values:
d = self.create_distribution([TESTFN])
for key in result_dict.keys():
self.assertNotIn(key, d.command_options.get('install', {}))
def test_command_packages_configfile(self):
sys.argv.append("build")
self.addCleanup(os.unlink, TESTFN)
@ -304,7 +364,7 @@ class MetadataTestCase(support.TempdirManager, support.EnvironGuard,
os.environ['HOME'] = temp_dir
files = dist.find_config_files()
self.assertIn(user_filename, files,
'%r not found in %r' % (user_filename, files))
'%r not found in %r' % (user_filename, files))
finally:
os.remove(user_filename)

View File

@ -49,6 +49,9 @@ Core and Builtins
Library
-------
- Issue #17732: Ignore distutils.cfg options pertaining to install paths if a
virtual environment is active.
- Issue #1159051: Back out a fix for handling corrupted gzip files that
broke backwards compatibility.