Repository: pypa/pip

Issue:
Option to look for pip.conf in conda environment
Related to issue ( https://github.com/conda-forge/conda-forge.github.io/pull/518 ).

Noted that there was some special handling with virtualenv to figure out the `pip.conf` file to use related to that environment. Was wondering if the same thing might be possible for a `conda` environment. Perhaps something like `$CONDA_PREFIX/pip/pip.conf` or something similar for both Unix and Windows (guessing with `.ini` as the extension). Though others may have thoughts on where this should live and how it should be named.

cc @kalefranz @msarahan @pradyunsg


Discussion:
Related point that we may want to consider is using a different configuration file for when `conda-build` is running vs. not.
Should add the `conda` package building considerations are independent from the active conda environment considerations.
I'm probably fine with it being at `os.path.join(sys.prefix, 'pip.conf')`, just like with virtualenv.

FYI, maybe not relevant here, but the canonical way to tell if a directory is a conda environment (and the way conda itself uses) is `os.path.isfile(os.path.join(sys.prefix, 'conda-meta', 'history'))`.
Thoughts @pfmoore? Would this be something pip would be interested in and/or accept a patch for?
@jakirkham I assume you're referring to the `running_under_virtualenv` function in pip? But I'd appreciate a more explicit pointer to the code that you mean.

Having `sys.base_prefix` differ from `sys.prefix` is defined by Python as the way to expose the fact that you're in a virtual environment (see [here](https://docs.python.org/3/library/venv.html#venv-def)). The use of `sys.real_prefix` is historically how `virtualenv` did this, and we handle that because prior to core Python support for virtual environments, `virtualenv` was the only solution around. IMO `virtualenv` should now switch to the standard `base_prefix` approach, and in the longer term, pip could drop checking for `real_prefix`.

I'd suggest that conda environments follow the core Python standard and set `base_prefix`, and then there would be no need for pip to special-case them, and other tools should also work without any special considerations.
Honestly don't really know the pip codebase well enough to propose where it should go. Was reading the docs, which sparked the question. :)

Interesting. Not sure to what extent using `base_prefix` is possible, but agree that sharing an API is a good idea if at all workable. This might work in some cases (e.g. `base_prefix` points at the `python` used by `conda` and `prefix` points to the `python` in the current environment if there is one). Not sure what to do when we are talking about the environment `conda` lives in (i.e. `root` later `base`) where both of these are the same though 😕 (added to the list below).

Can think of a few tricky cases though. There may be more. Not totally sure the implications off the top of my head, but we'd have to be sure we understand what `base_prefix` and `prefix` mean in these cases.

1. Activating `virtualenv` installed into a `conda` environment.
2. Environment stacking. ( https://github.com/conda/conda/pull/5159 )
3. Using [`build`/`host` in `conda-build`]( https://conda.io/docs/user-guide/tasks/build-packages/compiler-tools.html#anaconda-compilers-and-conda-build-3 ).
4. Using `pip.conf`/`pip.ini` in the `root`/`base` environment of `conda`.
> Honestly don't really know the pip codebase well enough to propose where it should go. Was reading the docs, which sparked the question. :)

Cool, I thought you were referring to what's in the code. I assume you were looking [in the docs here](https://pip.pypa.io/en/stable/user_guide/#config-file). Pip doesn't look at `$VIRTUAL_ENV`, but what it does is basically equivalent - the virtual environment config file is identified by pip as:

```python
        # finally virtualenv configuration first trumping others
        if running_under_virtualenv():
            yield kinds.VENV, [venv_config_file]
```

`venv_config_file` is simply `{sys.prefix}/pip.conf`, and `running_under_virtualenv` simply tests if `sys.prefix` differs from `sys.base_prefix` (or if `sys.real_prefix` is set).
That sounds right.

Ah ok thanks for the info.

What does `pip` do on Python 2 to detect a virtualenv?

So if we just drop a config file in `sys.prefix`, should that be enough for `pip`? Is there a way we can verify what config file it is using? Does being in a virtualenv actually affect this?
> What does pip do on Python 2 to detect a virtualenv?

`sys.real_prefix`. As I say, virtualenv sets that so pip will use that. But for conda, it's better to set `sys.base_prefix` as that's more forward compatible (you can set `sys.base_prefix` from user code in Python, both 2 and 3).

> So if we just drop a config file in sys.prefix, should that be enough for pip? Is there a way we can verify what config file it is using? Does being in a virtualenv actually affect this?

From the code I quoted, such a config file will only be used if you're in a virtualenv (i.e. `sys.base_prefix` is set and is not equal to `sys.prefix`). You can't verify "what config file pip is using", because it uses all of them - there's a hierarchy of files and config settings are taken from the highest-priority place the specific setting you're looked at is defined in. From the docs:

> If multiple configuration files are found by pip then they are combined in the following order:
>
> 1. Firstly the site-wide file is read, then
> 2. The per-user file is read, and finally
> 3. The virtualenv-specific file is read.
>
> Each file read overrides any values read from previous files, so if the global timeout is specified in both the site-wide file and the per-user file then the latter value is the one that will be used.
So I think it is important to point out that `conda` and `virtualenv` are coming at this from two different angles. Sorry if what follows is already obvious, want to establish a baseline before asking more questions.

AFAIK `virtualenv` allows one to create a separate environment for Python packages that links in an external Python (with batteries included) for use in this otherwise clean environment. Please correct me if I'm getting any of that wrong.

OTOH `conda` allows users to install Conda packages into an environment. Those may be (and a lot of them are) Python packages as well, but they are more similar to Python packages from a system package manager (e.g. `apt-get`). However a user can actually install a Conda package with a different Python interpreter altogether. In fact I have several environments with different Python interpreters and this is a common use case. It can also install dependencies of Python (e.g. OpenSSL) or things completely unrelated (e.g. Boost).

As a result of this, it's quite easy to have a version of Python installed in the `base` environment in `conda` that does not match the one in my active environment. Honestly one could be CPython and the other PyPy. So one of the things I'm trying to wrap my head around is what happens when `base_prefix` and `prefix` are not somehow related to the same Python. Namely what if `base_prefix` and `prefix` point to totally different, possibly incompatible Pythons? Related what happens when we mess with things like `base_prefix` under the hood give `site.py` seems to try and configure it (amongst other things)?

On a different point, the `base` environment in `conda` is technically just another environment. There's some special things that go into other environments to make sure that the `conda` CLI can be run when other environments are active (@kalefranz feel free to correct me if I'm missing anything here). Otherwise the `base` environment is no different than the other ones. The definitions of `base_prefix` and `prefix` really breakdown here as they should be the same. However we wouldn't want `base` to be treated as a somehow special environment from the other `conda` environments as it would break things for users not expecting this difference. How can we solve this issue?

Looking at the search priority might help to highlight the conceptual differences. Conda users typically think of each environment as being its own siloed `/usr` (or `/usr/local` if you would rather). The Anaconda and conda-forge stacks are even built up that way. For example, we provide our own certificates, which our copies of OpenSSL, curl, git, etc. are taught to look for. Users are free to build their own certificate package and replace ours, but it would still be expected to inhabit the same location relative to the prefix environment. So different environments could even have different certificates. Digression aside, we'd ideally want `pip.conf`/`pip.ini` in a conda environment to be treated as a site-wide file. Is that something we could achieve with the virtualenv approach or could we try another approach?
If I understand conda correctly, I don't think that the requested feature is really specific to conda (even though the original ask suggests that it is). I think it might be better worded as adding a config file that is specific to the *actual* Python install. On a Windows machine with the Python.org installers, this might be located at ``C:\Python36\pip.conf``, on a Linux machine it might be ``/usr/lib/python3.6/pip.conf``, in a Conda environment it'd be relative to that conda environment.
Thanks @dstufft. Agree that Python installers (batteries included) seems like an overlapping use case with similar end goals ( even if I wasn't thinking of that initially ;).
So, should we just unconditionally have `{sys.prefix}/pip.conf` as a configuration file location? I'm cool with that. Should be easy enough to implement too.

@pfmoore @dstufft Would you be fine with changing the "venv" to "site" for pip config, in 10.0.0? Otherwise, we could have a transition to remove venv references in configuration over the standard deprecation cycle, removing venv references in pip 11/12, if we want. I'm fine with either.

@pradyunsg I'm not sure that *unconditionally* having `{sys.prefix}/pip.conf` is right. Currently we only do that if we're in a venv - doing so when not isn't a change that anyone has requested as far as I know. Conda should be able to report itself as a virtual environment, by setting `sys.base_prefix` (that's how core Python expects virtual environments to report themselves as such).

This is not something I'm wiling to grant an exception for to put it in 10.0.0, as it's not a bug fix but a new feature. And regardless, I don't see why we should change `venv` -> `site`. The feature is there for virtual environments after all. (And I see conda environments as just another approach to virtual environments, so I'm using the term generically here, not limited to virtualenv/venv).
I got that feeler (unconditional addition) from Donald's comment.

I guess I'm trying to get too much into 10.0.0, as I said, I'm fine with
this happening after pip 10.0.0. =)

On Sun, 1 Apr 2018, 14:22 Paul Moore, <notifications@github.com> wrote:

> @pradyunsg <https://github.com/pradyunsg> I'm not sure that
> *unconditionally* having {sys.prefix}/pip.conf is right. Currently we
> only do that if we're in a venv - doing so when not isn't a change that
> anyone has requested as far as I know. Conda should be able to report
> itself as a virtual environment, by setting sys.base_prefix (that's how
> core Python expects virtual environments to report themselves as such).
>
> This is not something I'm wiling to grant an exception for to put it in
> 10.0.0, as it's not a bug fix but a new feature. And regardless, I don't
> see why we should change venv -> site. The feature is there for virtual
> environments after all. (And I see conda environments as just another
> approach to virtual environments, so I'm using the term generically here,
> not limited to virtualenv/venv).
>
> —
> You are receiving this because you were mentioned.
>
>
> Reply to this email directly, view it on GitHub
> <https://github.com/pypa/pip/issues/5060#issuecomment-377772686>, or mute
> the thread
> <https://github.com/notifications/unsubscribe-auth/ADH7SRgnZmxgaaVphT4QTmbC-bEYGwYBks5tkJVUgaJpZM4Sjm2w>
> .
>

I've had a few of the Linux distros ask for something similiar over time, so I think it's something that folks want (to let them provide some default configuration for pip). I don't think that it needs to get added to 10.0 though, and I don't know that ``{sys.prefix}/pip.conf`` is the *right* location for it either. I think this isn't a replacement for the virtual env config file though, and would rather be something that gets added before it in the resolution chain (and virtualenv config files override it).
> Conda should be able to report itself as a virtual environment, by setting sys.base_prefix (that's how core Python expects virtual environments to report themselves as such). ... And I see conda environments as just another approach to virtual environments, so I'm using the term generically here, not limited to virtualenv/venv

Unfortunately that's not really an accurate understanding of `conda`. Please read [comment]( https://github.com/pypa/pip/issues/5060#issuecomment-372854045 ) in detail if you haven't already. :)

The key take away is virtualenv's *link an external Python* into their environment. Conda environments install a *totally different Python* into their environment. So the distinction of where other Python's may exist relative to the active `conda` environment is irrelevant as they have no effect. The point gets even more muddied if we consider the environment where the `conda` executable lives (`base`).
OK, so conda environments are more like entire Python installations. OK. Pip currently doesn't have a per-installation config file. As @dstufft says, that's something we could add.
Right. The Linux package manager analogue is a pretty good one.
Has there been any progress on this? I'm in a related situation where my team has a separate (non-conda) installation of python, because we don't have root access on the machine, and would like a global pip config for our installation. I really expected it to look in {sys.prefix}/etc/pip.conf, or something. Is there a possibility of this being added?
Not really.

Looking at the discussion above again, ISTM the conclusion was that a per-installation configuration file has to be added, with its appropriate location, such that it's loaded just before venv configuration file.

I guess what's left is figuring out the location and actually doing the implementation.
Thanks @pradyunsg. So how do we go about deciding on the location? 
I want this badly enough to do the work :) (especially if/when I implement #6248, but right now for overriding the default index-url for a deployed environment - most of our deployments are full copies of Python that aren't tied to a system install at all but are wholly local to the directory they are in).

I assume it should be checking one (or more) of the paths that get listed when you do `python -m sysconfig` (even if we actually take it directly from `sys`), though I'm afraid I don't have enough info on a Windows install to decide which one 😄 

```
base = "C:\Python37_x64"
exec_prefix = "C:\Python37_x64"
installed_base = "C:\Python37_x64"
installed_platbase = "C:\Python37_x64"
platbase = "C:\Python37_x64"
prefix = "C:\Python37_x64"
projectbase = "C:\Python37_x64"
```

With a venv there's a bit more variety:
```
base = "C:\Projects\pip\.env2"
exec_prefix = "C:\Projects\pip\.env2"
installed_base = "C:\Python37_x64"
installed_platbase = "C:\Python37_x64"
platbase = "C:\Projects\pip\.env2"
prefix = "C:\Projects\pip\.env2"
projectbase = "C:\Projects\pip\.env2\Scripts"
```

So I'm thinking one of `base`, `prefix` or `exec_prefix`. But I don't actually know how those vary on other platforms and whether it matters. `sys.prefix` would have been my gut instinct.
FWIW here's the output from a Conda install on macOS (in the `base` environment). This is essentially the same for a Conda install on Linux.

```
data = "/zopt/conda3"
include = "/zopt/conda3/include/python3.6m"
platinclude = "/zopt/conda3/include/python3.6m"
platlib = "/zopt/conda3/lib/python3.6/site-packages"
platstdlib = "/zopt/conda3/lib/python3.6"
purelib = "/zopt/conda3/lib/python3.6/site-packages"
scripts = "/zopt/conda3/bin"
stdlib = "/zopt/conda3/lib/python3.6"
```

Here's the output from the system Python on macOS.

```
data = "/System/Library/Frameworks/Python.framework/Versions/2.7"
include = "/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7"
platinclude = "/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7"
platlib = "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages"
platstdlib = "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7"
purelib = "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages"
scripts = "/System/Library/Frameworks/Python.framework/Versions/2.7/bin"
stdlib = "/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7"
```

Also here's the output from CentOS 7's system Python.

```
data = "/usr"
include = "/usr/include/python2.7"
platinclude = "/usr/include/python2.7"
platlib = "/usr/lib64/python2.7/site-packages"
platstdlib = "/usr/lib64/python2.7"
purelib = "/usr/lib/python2.7/site-packages"
scripts = "/usr/bin"
stdlib = "/usr/lib64/python2.7"
```

Thus far `${data}/etc` looks like a good place to search. Though users are probably not messing with the internals of the macOS framework build (case 2).
`${data}/etc` has no cross-platform basis, unfortunately. What are the paths included in the `variables` section of the output (to match the ones that I copied)?

Another idea is to simply copy "whatever system is used for `sitecustomize.py`", since there's a good chance anyone customizing pip configuration here is also customizing Python configuration too.
Ah missed those, sorry. There was a lot of noise in the `variables` section (is there a good way to filter that?), but it seems `base` is the same as `data` in all 3 cases.
What about `prefix` and `exec_prefix`?
Both of those also appear to be the same as `base` and `data` in all 3 cases.

Resolving patch:
diff --git a/src/pip/_internal/commands/configuration.py b/src/pip/_internal/commands/configuration.py
--- a/src/pip/_internal/commands/configuration.py
+++ b/src/pip/_internal/commands/configuration.py
@@ -6,7 +6,8 @@
 from pip._internal.cli.status_codes import ERROR, SUCCESS
 from pip._internal.configuration import Configuration, kinds
 from pip._internal.exceptions import PipError
-from pip._internal.locations import venv_config_file
+from pip._internal.locations import running_under_virtualenv, site_config_file
+from pip._internal.utils.deprecation import deprecated
 from pip._internal.utils.misc import get_prog
 
 logger = logging.getLogger(__name__)
@@ -23,7 +24,7 @@ class ConfigurationCommand(Command):
         set: Set the name=value
         unset: Unset the value associated with name
 
-        If none of --user, --global and --venv are passed, a virtual
+        If none of --user, --global and --site are passed, a virtual
         environment configuration file is used if one is active and the file
         exists. Otherwise, all modifications happen on the to the user file by
         default.
@@ -73,12 +74,23 @@ def __init__(self, *args, **kwargs):
             help='Use the user configuration file only'
         )
 
+        self.cmd_opts.add_option(
+            '--site',
+            dest='site_file',
+            action='store_true',
+            default=False,
+            help='Use the current environment configuration file only'
+        )
+
         self.cmd_opts.add_option(
             '--venv',
             dest='venv_file',
             action='store_true',
             default=False,
-            help='Use the virtualenv configuration file only'
+            help=(
+                '[Deprecated] Use the current environment configuration '
+                'file in a virtual environment only'
+            )
         )
 
         self.parser.insert_option_group(0, self.cmd_opts)
@@ -127,27 +139,41 @@ def run(self, options, args):
         return SUCCESS
 
     def _determine_file(self, options, need_value):
-        file_options = {
-            kinds.USER: options.user_file,
-            kinds.GLOBAL: options.global_file,
-            kinds.VENV: options.venv_file
-        }
-
-        if sum(file_options.values()) == 0:
+        # Convert legacy venv_file option to site_file or error
+        if options.venv_file and not options.site_file:
+            if running_under_virtualenv():
+                options.site_file = True
+                deprecated(
+                    "The --venv option has been deprecated.",
+                    replacement="--site",
+                    gone_in="19.3",
+                )
+            else:
+                raise PipError(
+                    "Legacy --venv option requires a virtual environment. "
+                    "Use --site instead."
+                )
+
+        file_options = [key for key, value in (
+            (kinds.USER, options.user_file),
+            (kinds.GLOBAL, options.global_file),
+            (kinds.SITE, options.site_file),
+        ) if value]
+
+        if not file_options:
             if not need_value:
                 return None
-            # Default to user, unless there's a virtualenv file.
-            elif os.path.exists(venv_config_file):
-                return kinds.VENV
+            # Default to user, unless there's a site file.
+            elif os.path.exists(site_config_file):
+                return kinds.SITE
             else:
                 return kinds.USER
-        elif sum(file_options.values()) == 1:
-            # There's probably a better expression for this.
-            return [key for key in file_options if file_options[key]][0]
+        elif len(file_options) == 1:
+            return file_options[0]
 
         raise PipError(
             "Need exactly one file to operate upon "
-            "(--user, --venv, --global) to perform."
+            "(--user, --site, --global) to perform."
         )
 
     def list_values(self, options, args):
diff --git a/src/pip/_internal/configuration.py b/src/pip/_internal/configuration.py
--- a/src/pip/_internal/configuration.py
+++ b/src/pip/_internal/configuration.py
@@ -22,8 +22,7 @@
     ConfigurationError, ConfigurationFileCouldNotBeLoaded,
 )
 from pip._internal.locations import (
-    legacy_config_file, new_config_file, running_under_virtualenv,
-    site_config_files, venv_config_file,
+    global_config_files, legacy_config_file, new_config_file, site_config_file,
 )
 from pip._internal.utils.misc import ensure_dir, enum
 from pip._internal.utils.typing import MYPY_CHECK_RUNNING
@@ -59,7 +58,7 @@ def _disassemble_key(name):
 kinds = enum(
     USER="user",        # User Specific
     GLOBAL="global",    # System Wide
-    VENV="venv",        # Virtual Environment Specific
+    SITE="site",        # [Virtual] Environment Specific
     ENV="env",          # from PIP_CONFIG_FILE
     ENV_VAR="env-var",  # from Environment Variables
 )
@@ -83,7 +82,7 @@ def __init__(self, isolated, load_only=None):
         # type: (bool, Kind) -> None
         super(Configuration, self).__init__()
 
-        _valid_load_only = [kinds.USER, kinds.GLOBAL, kinds.VENV, None]
+        _valid_load_only = [kinds.USER, kinds.GLOBAL, kinds.SITE, None]
         if load_only not in _valid_load_only:
             raise ConfigurationError(
                 "Got invalid value for load_only - should be one of {}".format(
@@ -95,7 +94,7 @@ def __init__(self, isolated, load_only=None):
 
         # The order here determines the override order.
         self._override_order = [
-            kinds.GLOBAL, kinds.USER, kinds.VENV, kinds.ENV, kinds.ENV_VAR
+            kinds.GLOBAL, kinds.USER, kinds.SITE, kinds.ENV, kinds.ENV_VAR
         ]
 
         self._ignore_env_names = ["version", "help"]
@@ -352,7 +351,7 @@ def _iter_config_files(self):
             yield kinds.ENV, []
 
         # at the base we have any global configuration
-        yield kinds.GLOBAL, list(site_config_files)
+        yield kinds.GLOBAL, list(global_config_files)
 
         # per-user configuration next
         should_load_user_config = not self.isolated and not (
@@ -363,8 +362,7 @@ def _iter_config_files(self):
             yield kinds.USER, [legacy_config_file, new_config_file]
 
         # finally virtualenv configuration first trumping others
-        if running_under_virtualenv():
-            yield kinds.VENV, [venv_config_file]
+        yield kinds.SITE, [site_config_file]
 
     def _get_parser_to_modify(self):
         # type: () -> Tuple[str, RawConfigParser]
diff --git a/src/pip/_internal/locations.py b/src/pip/_internal/locations.py
--- a/src/pip/_internal/locations.py
+++ b/src/pip/_internal/locations.py
@@ -135,12 +135,12 @@ def virtualenv_no_global():
     if sys.platform[:6] == 'darwin' and sys.prefix[:16] == '/System/Library/':
         bin_py = '/usr/local/bin'
 
-site_config_files = [
+global_config_files = [
     os.path.join(path, config_basename)
     for path in appdirs.site_config_dirs('pip')
 ]
 
-venv_config_file = os.path.join(sys.prefix, config_basename)
+site_config_file = os.path.join(sys.prefix, config_basename)
 new_config_file = os.path.join(appdirs.user_config_dir("pip"), config_basename)
 
 


Test patch:
diff --git a/tests/unit/test_configuration.py b/tests/unit/test_configuration.py
--- a/tests/unit/test_configuration.py
+++ b/tests/unit/test_configuration.py
@@ -8,7 +8,7 @@
 
 from pip._internal.exceptions import ConfigurationError
 from pip._internal.locations import (
-    new_config_file, site_config_files, venv_config_file,
+    global_config_files, new_config_file, site_config_file,
 )
 from tests.lib.configuration_helpers import ConfigurationMixin, kinds
 
@@ -27,8 +27,8 @@ def test_user_loading(self):
         self.configuration.load()
         assert self.configuration.get_value("test.hello") == "2"
 
-    def test_venv_loading(self):
-        self.patch_configuration(kinds.VENV, {"test.hello": "3"})
+    def test_site_loading(self):
+        self.patch_configuration(kinds.SITE, {"test.hello": "3"})
 
         self.configuration.load()
         assert self.configuration.get_value("test.hello") == "3"
@@ -90,8 +90,8 @@ class TestConfigurationPrecedence(ConfigurationMixin):
     # Tests for methods to that determine the order of precedence of
     # configuration options
 
-    def test_env_overides_venv(self):
-        self.patch_configuration(kinds.VENV, {"test.hello": "1"})
+    def test_env_overides_site(self):
+        self.patch_configuration(kinds.SITE, {"test.hello": "1"})
         self.patch_configuration(kinds.ENV, {"test.hello": "0"})
         self.configuration.load()
 
@@ -111,16 +111,16 @@ def test_env_overides_global(self):
 
         assert self.configuration.get_value("test.hello") == "0"
 
-    def test_venv_overides_user(self):
+    def test_site_overides_user(self):
         self.patch_configuration(kinds.USER, {"test.hello": "2"})
-        self.patch_configuration(kinds.VENV, {"test.hello": "1"})
+        self.patch_configuration(kinds.SITE, {"test.hello": "1"})
         self.configuration.load()
 
         assert self.configuration.get_value("test.hello") == "1"
 
-    def test_venv_overides_global(self):
+    def test_site_overides_global(self):
         self.patch_configuration(kinds.GLOBAL, {"test.hello": "3"})
-        self.patch_configuration(kinds.VENV, {"test.hello": "1"})
+        self.patch_configuration(kinds.SITE, {"test.hello": "1"})
         self.configuration.load()
 
         assert self.configuration.get_value("test.hello") == "1"
@@ -141,8 +141,8 @@ def test_env_not_overriden_by_environment_var(self):
         assert self.configuration.get_value("test.hello") == "1"
         assert self.configuration.get_value(":env:.hello") == "5"
 
-    def test_venv_not_overriden_by_environment_var(self):
-        self.patch_configuration(kinds.VENV, {"test.hello": "2"})
+    def test_site_not_overriden_by_environment_var(self):
+        self.patch_configuration(kinds.SITE, {"test.hello": "2"})
         os.environ["PIP_HELLO"] = "5"
 
         self.configuration.load()
@@ -182,8 +182,8 @@ def test_no_specific_given_modification(self):
         else:
             assert False, "Should have raised an error."
 
-    def test_venv_modification(self):
-        self.configuration.load_only = kinds.VENV
+    def test_site_modification(self):
+        self.configuration.load_only = kinds.SITE
         self.configuration.load()
 
         # Mock out the method
@@ -192,9 +192,9 @@ def test_venv_modification(self):
 
         self.configuration.set_value("test.hello", "10")
 
-        # get the path to venv config file
+        # get the path to site config file
         assert mymock.call_count == 1
-        assert mymock.call_args[0][0] == venv_config_file
+        assert mymock.call_args[0][0] == site_config_file
 
     def test_user_modification(self):
         # get the path to local config file
@@ -224,4 +224,4 @@ def test_global_modification(self):
 
         # get the path to user config file
         assert mymock.call_count == 1
-        assert mymock.call_args[0][0] == site_config_files[-1]
+        assert mymock.call_args[0][0] == global_config_files[-1]
diff --git a/tests/unit/test_options.py b/tests/unit/test_options.py
--- a/tests/unit/test_options.py
+++ b/tests/unit/test_options.py
@@ -5,7 +5,8 @@
 
 import pip._internal.configuration
 from pip._internal import main
-from pip._internal.commands import DownloadCommand
+from pip._internal.commands import ConfigurationCommand, DownloadCommand
+from pip._internal.exceptions import PipError
 from tests.lib.options_helpers import AddFakeCommandMixin
 
 
@@ -383,19 +384,11 @@ def test_client_cert(self):
 class TestOptionsConfigFiles(object):
 
     def test_venv_config_file_found(self, monkeypatch):
-        # strict limit on the site_config_files list
+        # strict limit on the global_config_files list
         monkeypatch.setattr(
-            pip._internal.configuration, 'site_config_files', ['/a/place']
+            pip._internal.configuration, 'global_config_files', ['/a/place']
         )
 
-        # If we are running in a virtualenv and all files appear to exist,
-        # we should see two config files.
-        monkeypatch.setattr(
-            pip._internal.configuration,
-            'running_under_virtualenv',
-            lambda: True,
-        )
-        monkeypatch.setattr(os.path, 'exists', lambda filename: True)
         cp = pip._internal.configuration.Configuration(isolated=False)
 
         files = []
@@ -403,3 +396,50 @@ def test_venv_config_file_found(self, monkeypatch):
             files.extend(val)
 
         assert len(files) == 4
+
+    @pytest.mark.parametrize(
+        "args, expect",
+        (
+            ([], None),
+            (["--global"], "global"),
+            (["--site"], "site"),
+            (["--user"], "user"),
+            (["--global", "--user"], PipError),
+            (["--global", "--site"], PipError),
+            (["--global", "--site", "--user"], PipError),
+        )
+    )
+    def test_config_file_options(self, monkeypatch, args, expect):
+        cmd = ConfigurationCommand()
+        # Replace a handler with a no-op to avoid side effects
+        monkeypatch.setattr(cmd, "get_name", lambda *a: None)
+
+        options, args = cmd.parser.parse_args(args + ["get", "name"])
+        if expect is PipError:
+            with pytest.raises(PipError):
+                cmd._determine_file(options, need_value=False)
+        else:
+            assert expect == cmd._determine_file(options, need_value=False)
+
+    def test_config_file_venv_option(self, monkeypatch):
+        cmd = ConfigurationCommand()
+        # Replace a handler with a no-op to avoid side effects
+        monkeypatch.setattr(cmd, "get_name", lambda *a: None)
+
+        collected_warnings = []
+
+        def _warn(message, *a, **kw):
+            collected_warnings.append(message)
+        monkeypatch.setattr("warnings.warn", _warn)
+
+        options, args = cmd.parser.parse_args(["--venv", "get", "name"])
+        assert "site" == cmd._determine_file(options, need_value=False)
+        assert collected_warnings
+        assert "--site" in collected_warnings[0]
+
+        # No warning or error if both "--venv" and "--site" are specified
+        collected_warnings[:] = []
+        options, args = cmd.parser.parse_args(["--venv", "--site", "get",
+                                               "name"])
+        assert "site" == cmd._determine_file(options, need_value=False)
+        assert not collected_warnings