Repository: pypa/pip

Issue:
Basic auth credentials in --extra-index-urls are not used when specifying multiple under the same domain
- Pip version: 8.1.2
- Python version: 2.7.9
- Operating System: Debian Jessie (`uname -a` output: `Linux ip-10-254-0-170 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt25-2+deb8u3 (2016-07-02) x86_64 GNU/Linux`)
### Description:

I am trying to use two `--extra-index-url`s from packagecloud.io (we have two private indices at our office) but when I specify both I get prompted to log in to packagecloud. When I specify one or the other I do not. I think that pip is having trouble handling the basic auth for each index separately.
### What I've run:

This is the problematic command that I wish would work but does not:

```
$ pip install --user --upgrade \
    --extra-index-url https://<api token>:@packagecloud.io/2rs2ts/oldrepo/pypi/simple \
    --extra-index-url https://<other api token>:@packagecloud.io/2rs2ts/newrepo/pypi/simple \
    mypackage
Collecting mypackage
User for packagecloud.io:
```

I can work around it by specifying PyPI as an `--extra-index-url` and one of my private indices as the `--index`, which makes me think that this is a bug with `--extra-index-url`:

```
$ pip install --user --upgrade \
    --index https://<api token>:@packagecloud.io/2rs2ts/oldrepo/pypi/simple \
    --extra-index-url https://<other api token>:@packagecloud.io/2rs2ts/newrepo/pypi/simple \
    --extra-index-url https://pypi.python.org/simple \
    mypackage
Collecting mypackage
  Downloading https://packagecloud.io/2rs2ts/newrepo/pypi/packages/mypackage-1.0.0-py2-none-any.whl (52kB)
etc. etc.
```


Discussion:

Patch:
diff --git a/news/3931.bugfix.rst b/news/3931.bugfix.rst
new file mode 100644
index 000000000..0ebb9e495
--- /dev/null
+++ b/news/3931.bugfix.rst
@@ -0,0 +1,1 @@
+Prefer credentials from the URL over the previously-obtained credentials from URLs of the same domain, so it is possible to use different credentials on the same index server for different ``--extra-index-url`` options.
diff --git a/src/pip/_internal/network/auth.py b/src/pip/_internal/network/auth.py
index bd54a5cba..819687bae 100644
--- a/src/pip/_internal/network/auth.py
+++ b/src/pip/_internal/network/auth.py
@@ -170,13 +170,12 @@ class MultiDomainBasicAuth(AuthBase):
         """
         url, netloc, _ = split_auth_netloc_from_url(original_url)
 
-        # Use any stored credentials that we have for this netloc
-        username, password = self.passwords.get(netloc, (None, None))
+        # Try to get credentials from original url
+        username, password = self._get_new_credentials(original_url)
 
+        # If credentials not found, use any stored credentials for this netloc
         if username is None and password is None:
-            # No stored credentials. Acquire new credentials without prompting
-            # the user. (e.g. from netrc, keyring, or the URL itself)
-            username, password = self._get_new_credentials(original_url)
+            username, password = self.passwords.get(netloc, (None, None))
 
         if username is not None or password is not None:
             # Convert the username and password if they're None, so that


Test patch:
diff --git a/tests/unit/test_network_auth.py b/tests/unit/test_network_auth.py
index 44c739d86..ce528d0ac 100644
--- a/tests/unit/test_network_auth.py
+++ b/tests/unit/test_network_auth.py
@@ -47,11 +47,29 @@ def test_get_credentials_parses_correctly(input_url, url, username, password):
     )
 
 
-def test_get_credentials_uses_cached_credentials():
+def test_get_credentials_not_to_uses_cached_credentials():
     auth = MultiDomainBasicAuth()
     auth.passwords['example.com'] = ('user', 'pass')
 
     got = auth._get_url_and_credentials("http://foo:bar@example.com/path")
+    expected = ('http://example.com/path', 'foo', 'bar')
+    assert got == expected
+
+
+def test_get_credentials_not_to_uses_cached_credentials_only_username():
+    auth = MultiDomainBasicAuth()
+    auth.passwords['example.com'] = ('user', 'pass')
+
+    got = auth._get_url_and_credentials("http://foo@example.com/path")
+    expected = ('http://example.com/path', 'foo', '')
+    assert got == expected
+
+
+def test_get_credentials_uses_cached_credentials():
+    auth = MultiDomainBasicAuth()
+    auth.passwords['example.com'] = ('user', 'pass')
+
+    got = auth._get_url_and_credentials("http://example.com/path")
     expected = ('http://example.com/path', 'user', 'pass')
     assert got == expected