mirror of
https://github.com/pypa/pip
synced 2023-12-13 21:30:23 +01:00
Updated ConfigOptionParser to use both config file and environmental variables.
This commit is contained in:
parent
440f910222
commit
7a42612215
115
pip.py
115
pip.py
|
@ -17,7 +17,7 @@ import re
|
||||||
import shutil
|
import shutil
|
||||||
import fnmatch
|
import fnmatch
|
||||||
import operator
|
import operator
|
||||||
import stat
|
import copy
|
||||||
try:
|
try:
|
||||||
from hashlib import md5
|
from hashlib import md5
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -35,6 +35,7 @@ import httplib
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
import ConfigParser
|
import ConfigParser
|
||||||
|
from distutils.util import strtobool
|
||||||
|
|
||||||
class InstallationError(Exception):
|
class InstallationError(Exception):
|
||||||
"""General exception during installation"""
|
"""General exception during installation"""
|
||||||
|
@ -69,65 +70,81 @@ else:
|
||||||
lib_py = os.path.join(sys.prefix, 'lib', 'python%s' % sys.version[:3])
|
lib_py = os.path.join(sys.prefix, 'lib', 'python%s' % sys.version[:3])
|
||||||
bin_py = os.path.join(sys.prefix, 'bin')
|
bin_py = os.path.join(sys.prefix, 'bin')
|
||||||
CONFIG_NAME = '.pip.cfg'
|
CONFIG_NAME = '.pip.cfg'
|
||||||
|
|
||||||
class ConfigOptionParser(optparse.OptionParser):
|
class ConfigOptionParser(optparse.OptionParser):
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
self.config = ConfigParser.RawConfigParser()
|
self.config = ConfigParser.RawConfigParser()
|
||||||
self.files = []
|
self.name = kwargs.pop('name')
|
||||||
user_file = os.path.join(os.path.expanduser('~'), CONFIG_NAME)
|
self.files = self.get_config_files()
|
||||||
# FIXME: any other locations, e.g. cwd?
|
|
||||||
if os.path.isfile(user_file):
|
|
||||||
self.files.append(user_file)
|
|
||||||
self.config.read(self.files)
|
self.config.read(self.files)
|
||||||
|
assert self.name
|
||||||
optparse.OptionParser.__init__(self, *args, **kwargs)
|
optparse.OptionParser.__init__(self, *args, **kwargs)
|
||||||
|
|
||||||
def merge_from_config(self):
|
def get_config_files(self):
|
||||||
pip_section = self.get_section('pip')
|
return [os.path.join(os.path.expanduser('~'), CONFIG_NAME)]
|
||||||
self.set_defaults(config=pip_section)
|
|
||||||
|
|
||||||
def set_defaults(self, **kwargs):
|
def set_defaults(self, **kwargs):
|
||||||
"""Sets default values of parser options given the configuration file
|
"""Sets default values of parser options given the configuration file
|
||||||
"""
|
"""
|
||||||
defaults = {}
|
defaults = {}
|
||||||
config = kwargs.pop('config', None)
|
for key, val in kwargs.iteritems():
|
||||||
print "config", config
|
key = key.replace('_', '-')
|
||||||
if config:
|
if not key.startswith('--'):
|
||||||
for config_opt, config_value in config:
|
key = '--%s' % key # only prefer long opts
|
||||||
if not config_opt.startswith('--'):
|
option = self.get_option(key)
|
||||||
config_opt = '--%s' % config_opt # only prefer long opts
|
if option is not None:
|
||||||
option = self.get_option(config_opt)
|
# ignore empty values
|
||||||
print self.option_list
|
if not val:
|
||||||
if option is not None:
|
continue
|
||||||
config_value = config_value.split() # multiline configs
|
# multiline configs
|
||||||
if not config_value: ## ignore empty values
|
if option.action == 'append':
|
||||||
continue
|
val = val.split()
|
||||||
if option.action != 'append':
|
if option.action in ('store_true', 'store_false', 'count'):
|
||||||
config_value = config_value[0]
|
val = strtobool(val)
|
||||||
if option.action in ('store_true', 'store_false', 'count'):
|
defaults[option.dest] = val
|
||||||
config_value = strtobool(config_value)
|
|
||||||
defaults[option.dest] = config_value
|
|
||||||
else:
|
|
||||||
print "hmpf", config_opt
|
|
||||||
defaults = defaults or kwargs
|
|
||||||
optparse.OptionParser.set_defaults(self, **defaults)
|
optparse.OptionParser.set_defaults(self, **defaults)
|
||||||
|
|
||||||
def get_from_config(self, name, default=None, check_environ=True):
|
def get_config_section(self, name):
|
||||||
config = self.get_section('pip')
|
"""Get a section of a configuration"""
|
||||||
value = dict(config).get(name.replace('_', '-'), None)
|
if self.config.has_section(name):
|
||||||
if value is None and check_environ:
|
return self.config.items(name)
|
||||||
environ_name = 'PIP_%s' % name.upper()
|
|
||||||
value = os.environ.get(environ_name, None)
|
|
||||||
return value or default
|
|
||||||
|
|
||||||
def get_section(self, section):
|
|
||||||
"""Get section of a configuration"""
|
|
||||||
import pdb
|
|
||||||
#pdb.set_trace()
|
|
||||||
if self.config.has_section(section):
|
|
||||||
return self.config.items(section)
|
|
||||||
return []
|
return []
|
||||||
|
|
||||||
|
def get_environ_vars(self, prefix='PIP_'):
|
||||||
|
"""Returns a generator with all environmental vars with prefix PIP_"""
|
||||||
|
for key, val in os.environ.iteritems():
|
||||||
|
if key.startswith(prefix):
|
||||||
|
yield (key.replace(prefix, '').lower(), val)
|
||||||
|
|
||||||
|
def set_options_from_config_and_environ(self, defaults=None):
|
||||||
|
"""Sets the defaults of the option parser by merging in the config
|
||||||
|
files and environmental variables
|
||||||
|
|
||||||
|
This constitutes the following order of importance:
|
||||||
|
|
||||||
|
1. config files
|
||||||
|
a) global section
|
||||||
|
b) command section
|
||||||
|
2. environmental vars
|
||||||
|
3. program option
|
||||||
|
a) global flags
|
||||||
|
b) command flags
|
||||||
|
|
||||||
|
e.g.:
|
||||||
|
- --host=foo overrides $PIP_HOST=foo overrides [global] host = foo
|
||||||
|
- a setting made in the command specific config section overrides one
|
||||||
|
made in the global config section
|
||||||
|
- either are overriden by a environmental variable
|
||||||
|
- command line option flags override everything else
|
||||||
|
"""
|
||||||
|
if defaults is None:
|
||||||
|
defaults = {}
|
||||||
|
for section in ('global', self.name):
|
||||||
|
defaults.update(dict(self.get_config_section(section)))
|
||||||
|
defaults.update(dict(self.get_environ_vars()))
|
||||||
|
self.set_defaults(**defaults)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
pip_dist = pkg_resources.get_distribution('pip')
|
pip_dist = pkg_resources.get_distribution('pip')
|
||||||
version = '%s from %s (python %s)' % (
|
version = '%s from %s (python %s)' % (
|
||||||
|
@ -207,7 +224,8 @@ vcs = VcsSupport()
|
||||||
parser = ConfigOptionParser(
|
parser = ConfigOptionParser(
|
||||||
usage='%prog COMMAND [OPTIONS]',
|
usage='%prog COMMAND [OPTIONS]',
|
||||||
version=version,
|
version=version,
|
||||||
add_help_option=False)
|
add_help_option=False,
|
||||||
|
name='global')
|
||||||
|
|
||||||
parser.add_option(
|
parser.add_option(
|
||||||
'-h', '--help',
|
'-h', '--help',
|
||||||
|
@ -291,14 +309,13 @@ class Command(object):
|
||||||
self.parser = ConfigOptionParser(
|
self.parser = ConfigOptionParser(
|
||||||
usage=self.usage,
|
usage=self.usage,
|
||||||
prog='%s %s' % (sys.argv[0], self.name),
|
prog='%s %s' % (sys.argv[0], self.name),
|
||||||
version=parser.version)
|
version=parser.version,
|
||||||
|
name=self.name)
|
||||||
for option in parser.option_list:
|
for option in parser.option_list:
|
||||||
if not option.dest or option.dest == 'help':
|
if not option.dest or option.dest == 'help':
|
||||||
# -h, --version, etc
|
# -h, --version, etc
|
||||||
continue
|
continue
|
||||||
self.parser.add_option(option)
|
self.parser.add_option(option)
|
||||||
config_list = self.parser.get_section(self.name)
|
|
||||||
self.parser.set_defaults(**dict(config_list))
|
|
||||||
_commands[self.name] = self
|
_commands[self.name] = self
|
||||||
|
|
||||||
def merge_options(self, initial_options, options):
|
def merge_options(self, initial_options, options):
|
||||||
|
@ -309,9 +326,9 @@ class Command(object):
|
||||||
|
|
||||||
def main(self, complete_args, args, initial_options):
|
def main(self, complete_args, args, initial_options):
|
||||||
global logger
|
global logger
|
||||||
|
self.parser.set_options_from_config_and_environ()
|
||||||
options, args = self.parser.parse_args(args)
|
options, args = self.parser.parse_args(args)
|
||||||
self.merge_options(initial_options, options)
|
self.merge_options(initial_options, options)
|
||||||
self.parser.merge_from_config()
|
|
||||||
|
|
||||||
if args and args[-1] == '___VENV_RESTART___':
|
if args and args[-1] == '___VENV_RESTART___':
|
||||||
## FIXME: We don't do anything this this value yet:
|
## FIXME: We don't do anything this this value yet:
|
||||||
|
|
Loading…
Reference in a new issue