Hello community, here is the log from the commit of package python-pip for openSUSE:Factory checked in at 2019-08-16 15:28:31 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pip (Old) and /work/SRC/openSUSE:Factory/.python-pip.new.22127 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pip" Fri Aug 16 15:28:31 2019 rev:45 rq:723012 version:19.2.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pip/python-pip.changes 2019-08-09 16:49:06.953507884 +0200 +++ /work/SRC/openSUSE:Factory/.python-pip.new.22127/python-pip.changes 2019-08-16 15:28:39.189993668 +0200 @@ -1,0 +2,8 @@ +Tue Aug 13 08:19:21 UTC 2019 - [email protected] + +- Update to version 19.2.2: + * Merge pull request #6827 from cjerdonek/issue-6804-find-links-expansion + * Fix handling of tokens (single part credentials) in URLs (#6818) + * Simplify the handling of "typing.cast" + +------------------------------------------------------------------- Old: ---- pip-19.2.1.tar.xz New: ---- pip-19.2.2.tar.xz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pip.spec ++++++ --- /var/tmp/diff_new_pack.bbcoAz/_old 2019-08-16 15:28:40.001993489 +0200 +++ /var/tmp/diff_new_pack.bbcoAz/_new 2019-08-16 15:28:40.005993488 +0200 @@ -26,7 +26,7 @@ %bcond_with test %endif Name: python-pip%{psuffix} -Version: 19.2.1 +Version: 19.2.2 Release: 0 Summary: A Python package management system License: MIT ++++++ _service ++++++ --- /var/tmp/diff_new_pack.bbcoAz/_old 2019-08-16 15:28:40.037993480 +0200 +++ /var/tmp/diff_new_pack.bbcoAz/_new 2019-08-16 15:28:40.037993480 +0200 @@ -5,7 +5,7 @@ <param name="exclude">.git*</param> <param name="changesgenerate">enable</param> <param name="versionformat">@PARENT_TAG@</param> - <param name="revision">cb00488ca66acdeaae4b4353d1d8bdadc6340dce</param> + <param name="revision">082bc0411e9d17b3c80efed9237c61d7446515f5</param> </service> <service name="recompress" mode="disabled"> <param name="compression">xz</param> ++++++ _servicedata ++++++ --- /var/tmp/diff_new_pack.bbcoAz/_old 2019-08-16 15:28:40.061993475 +0200 +++ /var/tmp/diff_new_pack.bbcoAz/_new 2019-08-16 15:28:40.061993475 +0200 @@ -1,4 +1,4 @@ <servicedata> <service name="tar_scm"> <param name="url">https://github.com/pypa/pip</param> - <param name="changesrevision">cb00488ca66acdeaae4b4353d1d8bdadc6340dce</param></service></servicedata> \ No newline at end of file + <param name="changesrevision">082bc0411e9d17b3c80efed9237c61d7446515f5</param></service></servicedata> \ No newline at end of file ++++++ pip-19.2.1.tar.xz -> pip-19.2.2.tar.xz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pip-19.2.1/NEWS.rst new/pip-19.2.2/NEWS.rst --- old/pip-19.2.1/NEWS.rst 2019-07-23 20:41:33.000000000 +0200 +++ new/pip-19.2.2/NEWS.rst 2019-08-11 19:04:16.000000000 +0200 @@ -7,6 +7,17 @@ .. towncrier release notes start +19.2.2 (2019-08-11) +=================== + +Bug Fixes +--------- + +- Fix handling of tokens (single part credentials) in URLs. (`#6795 <https://github.com/pypa/pip/issues/6795>`_) +- Fix a regression that caused ``~`` expansion not to occur in ``--find-links`` + paths. (`#6804 <https://github.com/pypa/pip/issues/6804>`_) + + 19.2.1 (2019-07-23) =================== diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pip-19.2.1/src/pip/__init__.py new/pip-19.2.2/src/pip/__init__.py --- old/pip-19.2.1/src/pip/__init__.py 2019-07-23 20:41:33.000000000 +0200 +++ new/pip-19.2.2/src/pip/__init__.py 2019-08-11 19:04:16.000000000 +0200 @@ -1 +1 @@ -__version__ = "19.2.1" +__version__ = "19.2.2" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pip-19.2.1/src/pip/_internal/cli/cmdoptions.py new/pip-19.2.2/src/pip/_internal/cli/cmdoptions.py --- old/pip-19.2.1/src/pip/_internal/cli/cmdoptions.py 2019-07-23 20:41:33.000000000 +0200 +++ new/pip-19.2.2/src/pip/_internal/cli/cmdoptions.py 2019-08-11 19:04:16.000000000 +0200 @@ -370,9 +370,11 @@ ) index_urls = [] - search_scope = SearchScope( - find_links=options.find_links, - index_urls=index_urls, + # Make sure find_links is a list before passing to create(). + find_links = options.find_links or [] + + search_scope = SearchScope.create( + find_links=find_links, index_urls=index_urls, ) return search_scope diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pip-19.2.1/src/pip/_internal/download.py new/pip-19.2.2/src/pip/_internal/download.py --- old/pip-19.2.1/src/pip/_internal/download.py 2019-07-23 20:41:33.000000000 +0200 +++ new/pip-19.2.2/src/pip/_internal/download.py 2019-08-11 19:04:16.000000000 +0200 @@ -295,7 +295,7 @@ logger.debug("Found credentials in keyring for %s", netloc) return kr_auth - return None, None + return username, password def _get_url_and_credentials(self, original_url): """Return the credentials to use for the provided URL. @@ -312,15 +312,29 @@ # Use any stored credentials that we have for this netloc username, password = self.passwords.get(netloc, (None, None)) - # If nothing cached, acquire new credentials without prompting - # the user (e.g. from netrc, keyring, or similar). - if username is None or password is None: + 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) - if username is not None and password is not None: - # Store the username and password + if username is not None or password is not None: + # Convert the username and password if they're None, so that + # this netloc will show up as "cached" in the conditional above. + # Further, HTTPBasicAuth doesn't accept None, so it makes sense to + # cache the value that is going to be used. + username = username or "" + password = password or "" + + # Store any acquired credentials. self.passwords[netloc] = (username, password) + assert ( + # Credentials were found + (username is not None and password is not None) or + # Credentials were not found + (username is None and password is None) + ), "Could not load credentials from url: {}".format(original_url) + return url, username, password def __call__(self, req): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pip-19.2.1/src/pip/_internal/utils/misc.py new/pip-19.2.2/src/pip/_internal/utils/misc.py --- old/pip-19.2.1/src/pip/_internal/utils/misc.py 2019-07-23 20:41:33.000000000 +0200 +++ new/pip-19.2.2/src/pip/_internal/utils/misc.py 2019-08-11 19:04:16.000000000 +0200 @@ -48,21 +48,18 @@ if MYPY_CHECK_RUNNING: from typing import ( Any, AnyStr, Container, Iterable, List, Mapping, Match, Optional, Text, - Union, + Tuple, Union, cast, ) from pip._vendor.pkg_resources import Distribution from pip._internal.models.link import Link from pip._internal.utils.ui import SpinnerInterface -try: - from typing import cast, Tuple VersionInfo = Tuple[int, int, int] -except ImportError: - # typing's cast() isn't supported in code comments, so we need to - # define a dummy, no-op version. - def cast(typ, val): - return val - VersionInfo = None +else: + # typing's cast() is needed at runtime, but we don't want to import typing. + # Thus, we use a dummy no-op version, which we tell mypy to ignore. + def cast(type_, value): # type: ignore + return value __all__ = ['rmtree', 'display_path', 'backup_dir', @@ -135,7 +132,7 @@ elif len(py_version_info) > 3: py_version_info = py_version_info[:3] - return cast(VersionInfo, py_version_info) + return cast('VersionInfo', py_version_info) def ensure_dir(path): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pip-19.2.1/tests/unit/test_cmdoptions.py new/pip-19.2.2/tests/unit/test_cmdoptions.py --- old/pip-19.2.1/tests/unit/test_cmdoptions.py 2019-07-23 20:41:33.000000000 +0200 +++ new/pip-19.2.2/tests/unit/test_cmdoptions.py 2019-08-11 19:04:16.000000000 +0200 @@ -1,5 +1,8 @@ +import os + import pretend import pytest +from mock import patch from pip._internal.cli.cmdoptions import ( _convert_python_version, make_search_scope, @@ -7,20 +10,24 @@ @pytest.mark.parametrize( - 'no_index, suppress_no_index, expected_index_urls', [ - (False, False, ['default_url', 'url1', 'url2']), - (False, True, ['default_url', 'url1', 'url2']), - (True, False, []), + 'find_links, no_index, suppress_no_index, expected', [ + (['link1'], False, False, + (['link1'], ['default_url', 'url1', 'url2'])), + (['link1'], False, True, (['link1'], ['default_url', 'url1', 'url2'])), + (['link1'], True, False, (['link1'], [])), # Passing suppress_no_index=True suppresses no_index=True. - (True, True, ['default_url', 'url1', 'url2']), + (['link1'], True, True, (['link1'], ['default_url', 'url1', 'url2'])), + # Test options.find_links=False. + (False, False, False, ([], ['default_url', 'url1', 'url2'])), ], ) -def test_make_search_scope(no_index, suppress_no_index, expected_index_urls): +def test_make_search_scope(find_links, no_index, suppress_no_index, expected): """ - :param expected: the expected index_urls value. + :param expected: the expected (find_links, index_urls) values. """ + expected_find_links, expected_index_urls = expected options = pretend.stub( - find_links=['link1'], + find_links=find_links, index_url='default_url', extra_index_urls=['url1', 'url2'], no_index=no_index, @@ -28,10 +35,42 @@ search_scope = make_search_scope( options, suppress_no_index=suppress_no_index, ) - assert search_scope.find_links == ['link1'] + assert search_scope.find_links == expected_find_links assert search_scope.index_urls == expected_index_urls +@patch('pip._internal.utils.misc.expanduser') +def test_make_search_scope__find_links_expansion(mock_expanduser, tmpdir): + """ + Test "~" expansion in --find-links paths. + """ + # This is a mock version of expanduser() that expands "~" to the tmpdir. + def expand_path(path): + if path.startswith('~/'): + path = os.path.join(tmpdir, path[2:]) + return path + + mock_expanduser.side_effect = expand_path + + options = pretend.stub( + find_links=['~/temp1', '~/temp2'], + index_url='default_url', + extra_index_urls=[], + no_index=False, + ) + # Only create temp2 and not temp1 to test that "~" expansion only occurs + # when the directory exists. + temp2_dir = os.path.join(tmpdir, 'temp2') + os.mkdir(temp2_dir) + + search_scope = make_search_scope(options) + + # Only ~/temp2 gets expanded. Also, the path is normalized when expanded. + expected_temp2_dir = os.path.normcase(temp2_dir) + assert search_scope.find_links == ['~/temp1', expected_temp2_dir] + assert search_scope.index_urls == ['default_url'] + + @pytest.mark.parametrize('value, expected', [ ('', (None, None)), ('2', ((2,), None)), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pip-19.2.1/tests/unit/test_download.py new/pip-19.2.2/tests/unit/test_download.py --- old/pip-19.2.1/tests/unit/test_download.py 2019-07-23 20:41:33.000000000 +0200 +++ new/pip-19.2.2/tests/unit/test_download.py 2019-08-11 19:04:16.000000000 +0200 @@ -483,18 +483,53 @@ assert not hasattr(session.adapters["https://example.com/"], "cache") -def test_get_credentials(): [email protected](["input_url", "url", "username", "password"], [ + ( + "http://user%40email.com:[email protected]/path", + "http://example.com/path", + "[email protected]", + "password", + ), + ( + "http://username:[email protected]/path", + "http://example.com/path", + "username", + "password", + ), + ( + "http://[email protected]/path", + "http://example.com/path", + "token", + "", + ), + ( + "http://example.com/path", + "http://example.com/path", + None, + None, + ), +]) +def test_get_credentials_parses_correctly(input_url, url, username, password): auth = MultiDomainBasicAuth() get = auth._get_url_and_credentials # Check URL parsing - assert get("http://foo:[email protected]/path") \ - == ('http://example.com/path', 'foo', 'bar') - assert auth.passwords['example.com'] == ('foo', 'bar') + assert get(input_url) == (url, username, password) + assert ( + # There are no credentials in the URL + (username is None and password is None) or + # Credentials were found and "cached" appropriately + auth.passwords['example.com'] == (username, password) + ) + +def test_get_credentials_uses_cached_credentials(): + auth = MultiDomainBasicAuth() auth.passwords['example.com'] = ('user', 'pass') - assert get("http://foo:[email protected]/path") \ - == ('http://example.com/path', 'user', 'pass') + + got = auth._get_url_and_credentials("http://foo:[email protected]/path") + expected = ('http://example.com/path', 'user', 'pass') + assert got == expected def test_get_index_url_credentials(): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pip-19.2.1/tests/unit/test_unit_outdated.py new/pip-19.2.2/tests/unit/test_unit_outdated.py --- old/pip-19.2.1/tests/unit/test_unit_outdated.py 2019-07-23 20:41:33.000000000 +0200 +++ new/pip-19.2.2/tests/unit/test_unit_outdated.py 2019-08-11 19:04:16.000000000 +0200 @@ -58,7 +58,7 @@ def _options(): ''' Some default options that we pass to outdated.pip_version_check ''' return pretend.stub( - find_links=False, index_url='default_url', extra_index_urls=[], + find_links=[], index_url='default_url', extra_index_urls=[], no_index=False, pre=False, trusted_hosts=False, cache_dir='', )
