mirror of https://github.com/pypa/pip
119 lines
3.8 KiB
Python
119 lines
3.8 KiB
Python
|
"""Configuration management setup
|
||
|
"""
|
||
|
|
||
|
import re
|
||
|
import os
|
||
|
import sys
|
||
|
|
||
|
from pip._vendor.six.moves import configparser
|
||
|
from pip.locations import (
|
||
|
legacy_config_file, config_basename, running_under_virtualenv,
|
||
|
site_config_files
|
||
|
)
|
||
|
from pip.utils import appdirs
|
||
|
|
||
|
|
||
|
_environ_prefix_re = re.compile(r"^PIP_", re.I)
|
||
|
|
||
|
|
||
|
class Configuration(object):
|
||
|
"""Handles the loading of configuration files and providing an interface to
|
||
|
accessing data within them.
|
||
|
"""
|
||
|
|
||
|
def __init__(self):
|
||
|
self._configparser = configparser.RawConfigParser()
|
||
|
self._config = {}
|
||
|
|
||
|
def load_config_files(self, name, isolated):
|
||
|
"""Loads configuration from configuration files
|
||
|
"""
|
||
|
files = self._get_config_files(isolated)
|
||
|
|
||
|
if files:
|
||
|
self._configparser.read(files)
|
||
|
|
||
|
for section in ('global', name):
|
||
|
self._config.update(
|
||
|
self._normalize_keys(self._get_config_section(section))
|
||
|
)
|
||
|
|
||
|
def load_environment_vars(self):
|
||
|
"""Loads configuration from environment variables
|
||
|
"""
|
||
|
self._config.update(self._normalize_keys(self._get_environ_vars()))
|
||
|
|
||
|
def items(self):
|
||
|
"""Returns key-value pairs like dict.values() representing the loaded
|
||
|
configuration
|
||
|
"""
|
||
|
return self._config.items()
|
||
|
|
||
|
def _normalize_keys(self, items):
|
||
|
"""Return a config dictionary with normalized keys regardless of
|
||
|
whether the keys were specified in environment variables or in config
|
||
|
files"""
|
||
|
normalized = {}
|
||
|
for key, val in items:
|
||
|
key = key.replace('_', '-')
|
||
|
if key.startswith('--'):
|
||
|
key = key[2:] # only prefer long opts
|
||
|
normalized[key] = val
|
||
|
return normalized
|
||
|
|
||
|
def _get_environ_vars(self):
|
||
|
"""Returns a generator with all environmental vars with prefix PIP_"""
|
||
|
for key, val in os.environ.items():
|
||
|
if _environ_prefix_re.search(key):
|
||
|
yield (_environ_prefix_re.sub("", key).lower(), val)
|
||
|
|
||
|
def _get_config_files(self, isolated):
|
||
|
"""Returns configuration files in a defined order.
|
||
|
|
||
|
The order is that the first files are overridden by the latter files;
|
||
|
like what ConfigParser expects.
|
||
|
"""
|
||
|
# the files returned by this method will be parsed in order with the
|
||
|
# first files listed being overridden by later files in standard
|
||
|
# ConfigParser fashion
|
||
|
config_file = os.environ.get('PIP_CONFIG_FILE', False)
|
||
|
if config_file == os.devnull:
|
||
|
return []
|
||
|
|
||
|
# at the base we have any site-wide configuration
|
||
|
files = list(site_config_files)
|
||
|
|
||
|
# per-user configuration next
|
||
|
if not isolated:
|
||
|
if config_file and os.path.exists(config_file):
|
||
|
files.append(config_file)
|
||
|
else:
|
||
|
# This is the legacy config file, we consider it to be a lower
|
||
|
# priority than the new file location.
|
||
|
files.append(legacy_config_file)
|
||
|
|
||
|
# This is the new config file, we consider it to be a higher
|
||
|
# priority than the legacy file.
|
||
|
files.append(
|
||
|
os.path.join(
|
||
|
appdirs.user_config_dir("pip"),
|
||
|
config_basename,
|
||
|
)
|
||
|
)
|
||
|
|
||
|
# finally virtualenv configuration first trumping others
|
||
|
if running_under_virtualenv():
|
||
|
venv_config_file = os.path.join(
|
||
|
sys.prefix,
|
||
|
config_basename,
|
||
|
)
|
||
|
if os.path.exists(venv_config_file):
|
||
|
files.append(venv_config_file)
|
||
|
|
||
|
return files
|
||
|
|
||
|
def _get_config_section(self, section):
|
||
|
if self._configparser.has_section(section):
|
||
|
return self._configparser.items(section)
|
||
|
return []
|