Repository: pypa/pip

Issue:
pip 6.0 unconditionally uses the network to check for update
We run in a environment where we restrict the access to the internet. Currently, when we install our virtual env, pip always check for a update on the Pypi server and there is no way to disable it. 

The result is that several retries are performed thus slowing down pip install when an internet connection is not available. The default verbosity hides this and present an unresponsive session (nothing seems to be going on). Adding the option `-vvv` 

Maybe it could respect the `--no-index` option to avoid checking on the network?

Since I cannot change the verbose level of pip through virtualenv, here is the virtualenv's call to pip

```
$ pip -vvv install --ignore-installed --pre --use-wheel --no-index setuptools pip
Starting new HTTPS connection (1): pypi.python.org
Incremented Retry for (url='/pypi/pip/json'): Retry(total=4, connect=None, read=None, redirect=None)
Retrying (Retry(total=4, connect=None, read=None, redirect=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x0330C5B0>, 'Connection to pypi.python.org timed out. (connect timeout=15)')': /pypi/pip/json
Starting new HTTPS connection (2): pypi.python.org
Incremented Retry for (url='/pypi/pip/json'): Retry(total=3, connect=None, read=None, redirect=None)
Retrying (Retry(total=3, connect=None, read=None, redirect=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x0330C730>, 'Connection to pypi.python.org timed out. (connect timeout=15)')': /pypi/pip/json
Starting new HTTPS connection (3): pypi.python.org
Incremented Retry for (url='/pypi/pip/json'): Retry(total=2, connect=None, read=None, redirect=None)
Retrying (Retry(total=2, connect=None, read=None, redirect=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x0330C7F0>, 'Connection to pypi.python.org timed out. (connect timeout=15)')': /pypi/pip/json
Starting new HTTPS connection (4): pypi.python.org
Incremented Retry for (url='/pypi/pip/json'): Retry(total=1, connect=None, read=None, redirect=None)
Retrying (Retry(total=1, connect=None, read=None, redirect=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x0330C0F0>, 'Connection to pypi.python.org timed out. (connect timeout=15)')': /pypi/pip/json
Starting new HTTPS connection (5): pypi.python.org
Incremented Retry for (url='/pypi/pip/json'): Retry(total=0, connect=None, read=None, redirect=None)
Retrying (Retry(total=0, connect=None, read=None, redirect=None)) after connection broken by 'ConnectTimeoutError(<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x0330C290>, 'Connection to pypi.python.org timed out. (connect timeout=15)')': /pypi/pip/json
Starting new HTTPS connection (6): pypi.python.org
There was an error checking the latest version of pip
Traceback (most recent call last):
  File "r:\dev\git\buildtools\venv\test6\lib\site-packages\pip\utils\outdated.py", line 109, in pip_version_check
    headers={"Accept": "application/json"},
  File "r:\dev\git\buildtools\venv\test6\lib\site-packages\pip\_vendor\requests\sessions.py", line 473, in get
    return self.request('GET', url, **kwargs)
  File "r:\dev\git\buildtools\venv\test6\lib\site-packages\pip\download.py", line 332, in request
    return super(PipSession, self).request(method, url, *args, **kwargs)
  File "r:\dev\git\buildtools\venv\test6\lib\site-packages\pip\_vendor\requests\sessions.py", line 461, in request
    resp = self.send(prep, **send_kwargs)
  File "r:\dev\git\buildtools\venv\test6\lib\site-packages\pip\_vendor\requests\sessions.py", line 573, in send
    r = adapter.send(request, **kwargs)
  File "r:\dev\git\buildtools\venv\test6\lib\site-packages\pip\_vendor\cachecontrol\adapter.py", line 43, in send
    resp = super(CacheControlAdapter, self).send(request, **kw)
  File "r:\dev\git\buildtools\venv\test6\lib\site-packages\pip\_vendor\requests\adapters.py", line 419, in send
    raise ConnectTimeout(e, request=request)
ConnectTimeout: HTTPSConnectionPool(host='pypi.python.org', port=443): Max retries exceeded with url: /pypi/pip/json (Caused by ConnectTimeoutError(<pip._vendor.requests.packages.urllib3.connection.VerifiedHTTPSConnection object at 0x0334B290>, 'Connection to pypi.python.org timed out. (connect timeout=15)'))
I
...
```



Discussion:
You can disable it with `--disable-pip-version-check`, although maybe it should respect `--no-index` as well, and probably it should not use the retry mechanism.

Good to know! Can we use the option `--disable-pip-version-check` when using virtualenv? Through an environment variable maybe?

`PIP_DISABLE_PIP_VERSION_CHECK=1` should work I think.


Resolving patch:
diff --git a/pip/basecommand.py b/pip/basecommand.py
--- a/pip/basecommand.py
+++ b/pip/basecommand.py
@@ -63,13 +63,13 @@ def __init__(self, isolated=False):
         )
         self.parser.add_option_group(gen_opts)
 
-    def _build_session(self, options):
+    def _build_session(self, options, retries=None, timeout=None):
         session = PipSession(
             cache=(
                 normalize_path(os.path.join(options.cache_dir, "http"))
                 if options.cache_dir else None
             ),
-            retries=options.retries,
+            retries=retries if retries is not None else options.retries,
             insecure_hosts=options.trusted_hosts,
         )
 
@@ -82,8 +82,10 @@ def _build_session(self, options):
             session.cert = options.client_cert
 
         # Handle timeouts
-        if options.timeout:
-            session.timeout = options.timeout
+        if options.timeout or timeout:
+            session.timeout = (
+                timeout if timeout is not None else options.timeout
+            )
 
         # Handle configured proxies
         if options.proxy:
@@ -201,8 +203,12 @@ def main(self, args):
                 sys.exit(VIRTUALENV_NOT_FOUND)
 
         # Check if we're using the latest version of pip available
-        if not options.disable_pip_version_check:
-            with self._build_session(options) as session:
+        if (not options.disable_pip_version_check
+                and not getattr(options, "no_index", False)):
+            with self._build_session(
+                    options,
+                    retries=0,
+                    timeout=min(5, options.timeout)) as session:
                 pip_version_check(session)
 
         try:
diff --git a/pip/baseparser.py b/pip/baseparser.py
--- a/pip/baseparser.py
+++ b/pip/baseparser.py
@@ -4,6 +4,7 @@
 import sys
 import optparse
 import os
+import re
 import textwrap
 from distutils.util import strtobool
 
@@ -16,6 +17,9 @@
 from pip.utils import appdirs, get_terminal_size
 
 
+_environ_prefix_re = re.compile(r"^PIP_", re.I)
+
+
 class PrettyHelpFormatter(optparse.IndentedHelpFormatter):
     """A prettier/less verbose help formatter for optparse."""
 
@@ -239,11 +243,11 @@ def get_config_section(self, name):
             return self.config.items(name)
         return []
 
-    def get_environ_vars(self, prefix='PIP_'):
+    def get_environ_vars(self):
         """Returns a generator with all environmental vars with prefix PIP_"""
         for key, val in os.environ.items():
-            if key.startswith(prefix):
-                yield (key.replace(prefix, '').lower(), val)
+            if _environ_prefix_re.search(key):
+                yield (_environ_prefix_re.sub("", key).lower(), val)
 
     def get_default_values(self):
         """Overridding to make updating the defaults after instantiation of
diff --git a/pip/cmdoptions.py b/pip/cmdoptions.py
--- a/pip/cmdoptions.py
+++ b/pip/cmdoptions.py
@@ -406,7 +406,7 @@ def make(self):
     action="store_true",
     default=False,
     help="Don't periodically check PyPI to determine whether a new version "
-         "of pip is available for download.")
+         "of pip is available for download. Implied with --no-index.")
 
 ##########
 # groups #


Test patch:
diff --git a/tests/conftest.py b/tests/conftest.py
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -106,6 +106,9 @@ def isolate(tmpdir):
     os.environ["GIT_AUTHOR_NAME"] = "pip"
     os.environ["GIT_AUTHOR_EMAIL"] = "pypa-dev@googlegroups.com"
 
+    # We want to disable the version check from running in the tests
+    os.environ["PIP_DISABLE_PIP_VERSION_CHECK"] = "true"
+
     os.makedirs(os.path.join(home_dir, ".config", "git"))
     with open(os.path.join(home_dir, ".config", "git", "config"), "wb") as fp:
         fp.write(