Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-google-auth-oauthlib for openSUSE:Factory checked in at 2022-04-13 21:06:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-google-auth-oauthlib (Old) and /work/SRC/openSUSE:Factory/.python-google-auth-oauthlib.new.1900 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-auth-oauthlib" Wed Apr 13 21:06:14 2022 rev:7 rq:969866 version:0.5.1 Changes: -------- --- /work/SRC/openSUSE:Factory/python-google-auth-oauthlib/python-google-auth-oauthlib.changes 2021-08-23 10:09:04.852182655 +0200 +++ /work/SRC/openSUSE:Factory/.python-google-auth-oauthlib.new.1900/python-google-auth-oauthlib.changes 2022-04-13 21:07:08.660687409 +0200 @@ -1,0 +2,10 @@ +Wed Apr 13 11:59:18 UTC 2022 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- Update to 0.5.1 + * avoid deprecated "out-of-band" authentication flow (#186) +- from version 0.5.0 + * deprecate OAuth out-of-band flow (#175) +- from version 0.4.6 + * remove dependency on `six` (#146), closes (#145) + +------------------------------------------------------------------- Old: ---- google-auth-oauthlib-0.4.5.tar.gz New: ---- google-auth-oauthlib-0.5.1.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-google-auth-oauthlib.spec ++++++ --- /var/tmp/diff_new_pack.Infm0U/_old 2022-04-13 21:07:09.232687986 +0200 +++ /var/tmp/diff_new_pack.Infm0U/_new 2022-04-13 21:07:09.240687994 +0200 @@ -1,7 +1,7 @@ # # spec file for package python-google-auth-oauthlib # -# Copyright (c) 2021 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,7 +19,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} %bcond_without python2 Name: python-google-auth-oauthlib -Version: 0.4.5 +Version: 0.5.1 Release: 0 Summary: Google authentication library License: Apache-2.0 ++++++ google-auth-oauthlib-0.4.5.tar.gz -> google-auth-oauthlib-0.5.1.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/PKG-INFO new/google-auth-oauthlib-0.5.1/PKG-INFO --- old/google-auth-oauthlib-0.4.5/PKG-INFO 2021-07-29 18:53:15.098886000 +0200 +++ new/google-auth-oauthlib-0.5.1/PKG-INFO 2022-03-15 16:59:55.817356600 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-auth-oauthlib -Version: 0.4.5 +Version: 0.5.1 Summary: Google Authentication Library Home-page: https://github.com/GoogleCloudPlatform/google-auth-library-python-oauthlib Author: Google Cloud Platform @@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License @@ -32,7 +33,7 @@ This library provides `oauthlib`_ integration with `google-auth`_. -.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=master +.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=main :target: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib .. |docs| image:: https://readthedocs.org/projects/google-auth-oauthlib/badge/?version=latest :target: https://google-auth-oauthlib.readthedocs.io/en/latest/ @@ -58,11 +59,24 @@ .. _google-auth-oauthlib.readthedocs.io: http://google-auth-oauthlib.readthedocs.io/ +Supported Python Versions +------------------------- +Python >= 3.6 + + +Unsupported Python Versions +--------------------------- + +Python == 2.7, Python == 3.5. + +The last version of this library compatible with Python 2.7 and 3.5 is +`google-auth-oauthlib==0.4.1`. + License ------- Apache 2.0 - See `the LICENSE`_ for more information. -.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/master/LICENSE +.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/main/LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/README.rst new/google-auth-oauthlib-0.5.1/README.rst --- old/google-auth-oauthlib-0.4.5/README.rst 2021-07-29 18:50:38.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/README.rst 2022-03-15 16:57:03.000000000 +0100 @@ -5,7 +5,7 @@ This library provides `oauthlib`_ integration with `google-auth`_. -.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=master +.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=main :target: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib .. |docs| image:: https://readthedocs.org/projects/google-auth-oauthlib/badge/?version=latest :target: https://google-auth-oauthlib.readthedocs.io/en/latest/ @@ -31,9 +31,22 @@ .. _google-auth-oauthlib.readthedocs.io: http://google-auth-oauthlib.readthedocs.io/ +Supported Python Versions +------------------------- +Python >= 3.6 + + +Unsupported Python Versions +--------------------------- + +Python == 2.7, Python == 3.5. + +The last version of this library compatible with Python 2.7 and 3.5 is +`google-auth-oauthlib==0.4.1`. + License ------- Apache 2.0 - See `the LICENSE`_ for more information. -.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/master/LICENSE +.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/main/LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/google_auth_oauthlib/flow.py new/google-auth-oauthlib-0.5.1/google_auth_oauthlib/flow.py --- old/google-auth-oauthlib-0.4.5/google_auth_oauthlib/flow.py 2021-07-29 18:50:38.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/google_auth_oauthlib/flow.py 2022-03-15 16:57:03.000000000 +0100 @@ -15,46 +15,44 @@ """OAuth 2.0 Authorization Flow This module provides integration with `requests-oauthlib`_ for running the -`OAuth 2.0 Authorization Flow`_ and acquiring user credentials. +`OAuth 2.0 Authorization Flow`_ and acquiring user credentials. See +`Using OAuth 2.0 to Access Google APIs`_ for an overview of OAuth 2.0 +authorization scenarios Google APIs support. -Here's an example of using :class:`Flow` with the installed application -authorization flow:: +Here's an example of using :class:`InstalledAppFlow`:: - from google_auth_oauthlib.flow import Flow + from google_auth_oauthlib.flow import InstalledAppFlow # Create the flow using the client secrets file from the Google API # Console. - flow = Flow.from_client_secrets_file( - 'path/to/client_secrets.json', - scopes=['profile', 'email'], - redirect_uri='urn:ietf:wg:oauth:2.0:oob') - - # Tell the user to go to the authorization URL. - auth_url, _ = flow.authorization_url(prompt='consent') - - print('Please go to this URL: {}'.format(auth_url)) - - # The user will get an authorization code. This code is used to get the - # access token. - code = input('Enter the authorization code: ') - flow.fetch_token(code=code) + flow = InstalledAppFlow.from_client_secrets_file( + 'client_secrets.json', + scopes=['profile', 'email']) + + flow.run_local_server() # You can use flow.credentials, or you can just get a requests session # using flow.authorized_session. session = flow.authorized_session() - print(session.get('https://www.googleapis.com/userinfo/v2/me').json()) -This particular flow can be handled entirely by using -:class:`InstalledAppFlow`. + profile_info = session.get( + 'https://www.googleapis.com/userinfo/v2/me').json() + + print(profile_info) + # {'name': '...', 'email': '...', ...} .. _requests-oauthlib: http://requests-oauthlib.readthedocs.io/en/stable/ .. _OAuth 2.0 Authorization Flow: https://tools.ietf.org/html/rfc6749#section-1.2 +.. _Using OAuth 2.0 to Access Google APIs: + https://developers.google.com/identity/protocols/oauth2 + """ from base64 import urlsafe_b64encode import hashlib import json import logging +import warnings try: from secrets import SystemRandom @@ -67,12 +65,16 @@ import google.auth.transport.requests import google.oauth2.credentials -from six.moves import input import google_auth_oauthlib.helpers _LOGGER = logging.getLogger(__name__) +_OOB_REDIRECT_URIS = [ + "urn:ietf:wg:oauth:2.0:oob", + "urn:ietf:wg:oauth:2.0:oob:auto", + "oob", +] class Flow(object): @@ -120,7 +122,7 @@ code_verifier. .. _client secrets: https://github.com/googleapis/google-api-python-client/blob - /master/docs/client-secrets.md + /main/docs/client-secrets.md """ self.client_type = client_type """str: The client type, either ``'web'`` or ``'installed'``""" @@ -153,8 +155,7 @@ format. .. _client secrets: - https://github.com/googleapis/google-api-python-client/blob/ - master/docs/client-secrets.md + https://github.com/googleapis/google-api-python-client/blob/main/docs/client-secrets.md """ if "web" in client_config: client_type = "web" @@ -213,6 +214,17 @@ @redirect_uri.setter def redirect_uri(self, value): + if value in _OOB_REDIRECT_URIS: + warnings.warn( + "'{}' is an OOB redirect URI. The OAuth out-of-band (OOB) flow is deprecated. " + "New clients will be unable to use this flow starting on Feb 28, 2022. " + "This flow will be deprecated for all clients on Oct 3, 2022. " + "Migrate to an alternative flow. " + "See https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html?m=1#disallowed-oob".format( + value + ), + DeprecationWarning, + ) self.oauth2session.redirect_uri = value def authorization_url(self, **kwargs): @@ -327,9 +339,7 @@ local development or applications that are installed on a desktop operating system. - This flow has two strategies: The console strategy provided by - :meth:`run_console` and the local server strategy provided by - :meth:`run_local_server`. + This flow uses a local server strategy provided by :meth:`run_local_server`. Example:: @@ -350,14 +360,14 @@ # {'name': '...', 'email': '...', ...} - Note that these aren't the only two ways to accomplish the installed - application flow, they are just the most common ways. You can use the + Note that this isn't the only way to accomplish the installed + application flow, just one of the most common. You can use the :class:`Flow` class to perform the same flow with different methods of presenting the authorization URL to the user or obtaining the authorization response, such as using an embedded web view. .. _Installed Application Authorization Flow: - https://github.com/googleapis/google-api-python-client/blob/master/docs/oauth-installed.md + https://github.com/googleapis/google-api-python-client/blob/main/docs/oauth-installed.md """ _OOB_REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob" @@ -383,6 +393,15 @@ ): """Run the flow using the console strategy. + .. deprecated:: 0.5.0 + Use :meth:`run_local_server` instead. + + The OAuth out-of-band (OOB) flow is deprecated. New clients will be unable to + use this flow starting on Feb 28, 2022. This flow will be deprecated + for all clients on Oct 3, 2022. Migrate to an alternative flow. + + See https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html?m=1#disallowed-oob" + The console strategy instructs the user to open the authorization URL in their browser. Once the authorization is complete the authorization server will give the user a code. The user then must copy & paste this @@ -401,6 +420,13 @@ for the user. """ kwargs.setdefault("prompt", "consent") + warnings.warn( + "New clients will be unable to use `InstalledAppFlow.run_console` " + "starting on Feb 28, 2022. All clients will be unable to use this method starting on Oct 3, 2022. " + "Use `InstalledAppFlow.run_local_server` instead. For details on the OOB flow deprecation, " + "see https://developers.googleblog.com/2022/02/making-oauth-flows-safer.html?m=1#disallowed-oob", + DeprecationWarning, + ) self.redirect_uri = self._OOB_REDIRECT_URI diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/google_auth_oauthlib/helpers.py new/google-auth-oauthlib-0.5.1/google_auth_oauthlib/helpers.py --- old/google-auth-oauthlib-0.4.5/google_auth_oauthlib/helpers.py 2021-07-29 18:50:38.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/google_auth_oauthlib/helpers.py 2022-03-15 16:57:03.000000000 +0100 @@ -51,8 +51,7 @@ oauthlib session and the validated client configuration. .. _client secrets: - https://github.com/googleapis/google-api-python-client/blob/master/ - docs/client-secrets.md + https://github.com/googleapis/google-api-python-client/blob/main/docs/client-secrets.md """ if "web" in client_config: @@ -89,8 +88,7 @@ oauthlib session and the validated client configuration. .. _client secrets: - https://github.com/googleapis/google-api-python-client/blob/master/ - docs/client-secrets.md + https://github.com/googleapis/google-api-python-client/blob/main/docs/client-secrets.md """ with open(client_secrets_file, "r") as json_file: client_config = json.load(json_file) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/google_auth_oauthlib/interactive.py new/google-auth-oauthlib-0.5.1/google_auth_oauthlib/interactive.py --- old/google-auth-oauthlib-0.4.5/google_auth_oauthlib/interactive.py 2021-07-29 18:50:38.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/google_auth_oauthlib/interactive.py 2022-03-15 16:57:03.000000000 +0100 @@ -21,10 +21,68 @@ from __future__ import absolute_import +import contextlib +import socket + import google_auth_oauthlib.flow -def get_user_credentials(scopes, client_id, client_secret): +LOCALHOST = "localhost" +DEFAULT_PORTS_TO_TRY = 100 + + +def is_port_open(port): + """Check if a port is open on localhost. + Based on StackOverflow answer: https://stackoverflow.com/a/43238489/101923 + Parameters + ---------- + port : int + A port to check on localhost. + Returns + ------- + is_open : bool + True if a socket can be opened at the requested port. + """ + with contextlib.closing(socket.socket(socket.AF_INET, socket.SOCK_STREAM)) as sock: + try: + sock.bind((LOCALHOST, port)) + sock.listen(1) + except socket.error: + is_open = False + else: + is_open = True + return is_open + + +def find_open_port(start=8080, stop=None): + """Find an open port between ``start`` and ``stop``. + Parameters + ---------- + start : Optional[int] + Beginning of range of ports to try. Defaults to 8080. + stop : Optional[int] + End of range of ports to try (not including exactly equals ``stop``). + This function tries 100 possible ports if no ``stop`` is specified. + Returns + ------- + Optional[int] + ``None`` if no open port is found, otherwise an integer indicating an + open port. + """ + if not stop: + stop = start + DEFAULT_PORTS_TO_TRY + + for port in range(start, stop): + if is_port_open(port): + return port + + # No open ports found. + return None + + +def get_user_credentials( + scopes, client_id, client_secret, minimum_port=8080, maximum_port=None +): """Gets credentials associated with your Google user account. This function authenticates using your user credentials by going through @@ -53,6 +111,12 @@ A string that verifies your application to Google APIs. Find this value in the `Credentials page on the Google Developer's Console <https://console.developers.google.com/apis/credentials>`_. + minimum_port (int): + Beginning of range of ports to try for redirect URI HTTP server. + Defaults to 8080. + maximum_port (Optional[int]): + End of range of ports to try (not including exactly equals ``stop``). + This function tries 100 possible ports if no ``stop`` is specified. Returns: google.oauth2.credentials.Credentials: @@ -102,4 +166,8 @@ client_config, scopes=scopes ) - return app_flow.run_console() + port = find_open_port() + if not port: + raise ConnectionError("Could not find open port.") + + return app_flow.run_local_server(host=LOCALHOST, port=port) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/google_auth_oauthlib.egg-info/PKG-INFO new/google-auth-oauthlib-0.5.1/google_auth_oauthlib.egg-info/PKG-INFO --- old/google-auth-oauthlib-0.4.5/google_auth_oauthlib.egg-info/PKG-INFO 2021-07-29 18:53:14.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/google_auth_oauthlib.egg-info/PKG-INFO 2022-03-15 16:59:55.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: google-auth-oauthlib -Version: 0.4.5 +Version: 0.5.1 Summary: Google Authentication Library Home-page: https://github.com/GoogleCloudPlatform/google-auth-library-python-oauthlib Author: Google Cloud Platform @@ -13,6 +13,7 @@ Classifier: Programming Language :: Python :: 3.7 Classifier: Programming Language :: Python :: 3.8 Classifier: Programming Language :: Python :: 3.9 +Classifier: Programming Language :: Python :: 3.10 Classifier: Development Status :: 3 - Alpha Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: Apache Software License @@ -32,7 +33,7 @@ This library provides `oauthlib`_ integration with `google-auth`_. -.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=master +.. |build| image:: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib.svg?branch=main :target: https://travis-ci.org/googleapis/google-auth-library-python-oauthlib .. |docs| image:: https://readthedocs.org/projects/google-auth-oauthlib/badge/?version=latest :target: https://google-auth-oauthlib.readthedocs.io/en/latest/ @@ -58,11 +59,24 @@ .. _google-auth-oauthlib.readthedocs.io: http://google-auth-oauthlib.readthedocs.io/ +Supported Python Versions +------------------------- +Python >= 3.6 + + +Unsupported Python Versions +--------------------------- + +Python == 2.7, Python == 3.5. + +The last version of this library compatible with Python 2.7 and 3.5 is +`google-auth-oauthlib==0.4.1`. + License ------- Apache 2.0 - See `the LICENSE`_ for more information. -.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/master/LICENSE +.. _the LICENSE: https://github.com/googleapis/google-auth-library-python-oauthlib/blob/main/LICENSE diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/google_auth_oauthlib.egg-info/entry_points.txt new/google-auth-oauthlib-0.5.1/google_auth_oauthlib.egg-info/entry_points.txt --- old/google-auth-oauthlib-0.4.5/google_auth_oauthlib.egg-info/entry_points.txt 2021-07-29 18:53:14.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/google_auth_oauthlib.egg-info/entry_points.txt 2022-03-15 16:59:55.000000000 +0100 @@ -1,3 +1,2 @@ [console_scripts] google-oauthlib-tool = google_auth_oauthlib.tool.__main__:main [tool] - diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/setup.py new/google-auth-oauthlib-0.5.1/setup.py --- old/google-auth-oauthlib-0.4.5/setup.py 2021-07-29 18:50:38.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/setup.py 2022-03-15 16:57:03.000000000 +0100 @@ -27,7 +27,7 @@ long_description = fh.read() -version = "0.4.5" +version = "0.5.1" setup( name="google-auth-oauthlib", @@ -54,6 +54,7 @@ "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", "Development Status :: 3 - Alpha", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/tests/unit/test_flow.py new/google-auth-oauthlib-0.5.1/tests/unit/test_flow.py --- old/google-auth-oauthlib-0.4.5/tests/unit/test_flow.py 2021-07-29 18:50:38.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/tests/unit/test_flow.py 2022-03-15 16:57:03.000000000 +0100 @@ -24,7 +24,7 @@ import mock import pytest import requests -from six.moves import urllib +import urllib from google_auth_oauthlib import flow @@ -58,6 +58,20 @@ == mock.sentinel.redirect_uri ) + def test_from_client_secrets_file_with_oob_redirect_uri(self): + with pytest.deprecated_call(): + instance = flow.Flow.from_client_secrets_file( + CLIENT_SECRETS_FILE, + scopes=mock.sentinel.scopes, + redirect_uri="urn:ietf:wg:oauth:2.0:oob", + ) + + assert ( + instance.redirect_uri + == instance.oauth2session.redirect_uri + == "urn:ietf:wg:oauth:2.0:oob" + ) + def test_from_client_config_installed(self): client_config = {"installed": CLIENT_SECRETS_INFO["web"]} instance = flow.Flow.from_client_config( @@ -282,11 +296,13 @@ with fetch_token_patch as fetch_token_mock: yield fetch_token_mock - @mock.patch("google_auth_oauthlib.flow.input", autospec=True) + @mock.patch("builtins.input", autospec=True) def test_run_console(self, input_mock, instance, mock_fetch_token): input_mock.return_value = mock.sentinel.code instance.code_verifier = "amanaplanacanalpanama" - credentials = instance.run_console() + + with pytest.deprecated_call(): + credentials = instance.run_console() assert credentials.token == mock.sentinel.access_token assert credentials._refresh_token == mock.sentinel.refresh_token diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/google-auth-oauthlib-0.4.5/tests/unit/test_interactive.py new/google-auth-oauthlib-0.5.1/tests/unit/test_interactive.py --- old/google-auth-oauthlib-0.4.5/tests/unit/test_interactive.py 2021-07-29 18:50:38.000000000 +0200 +++ new/google-auth-oauthlib-0.5.1/tests/unit/test_interactive.py 2022-03-15 16:57:03.000000000 +0100 @@ -12,7 +12,47 @@ # See the License for the specific language governing permissions and # limitations under the License. +import socket + import mock +import pytest + + +def test_find_open_port_finds_start_port(monkeypatch): + from google_auth_oauthlib import interactive as module_under_test + + monkeypatch.setattr(socket, "socket", mock.create_autospec(socket.socket)) + port = module_under_test.find_open_port(9999) + assert port == 9999 + + +def test_find_open_port_finds_stop_port(monkeypatch): + from google_auth_oauthlib import interactive as module_under_test + + socket_instance = mock.create_autospec(socket.socket, instance=True) + + def mock_socket(family, type_): + return socket_instance + + monkeypatch.setattr(socket, "socket", mock_socket) + socket_instance.listen.side_effect = [socket.error] * 99 + [None] + port = module_under_test.find_open_port(9000, stop=9100) + assert port == 9099 + + +def test_find_open_port_returns_none(monkeypatch): + from google_auth_oauthlib import interactive as module_under_test + + socket_instance = mock.create_autospec(socket.socket, instance=True) + + def mock_socket(family, type_): + return socket_instance + + monkeypatch.setattr(socket, "socket", mock_socket) + socket_instance.listen.side_effect = socket.error + port = module_under_test.find_open_port(9000) + assert port is None + socket_instance.listen.assert_has_calls(mock.call(1) for _ in range(100)) def test_get_user_credentials(): @@ -33,4 +73,25 @@ actual_client_config = mock_flow.from_client_config.call_args[0][0] assert actual_client_config["installed"]["client_id"] == "some-client-id" assert actual_client_config["installed"]["client_secret"] == "shh-secret" - mock_flow_instance.run_console.assert_called_once() + mock_flow_instance.run_local_server.assert_called_once() + + +def test_get_user_credentials_raises_connectionerror(monkeypatch): + from google_auth_oauthlib import flow + from google_auth_oauthlib import interactive as module_under_test + + def mock_find_open_port(): + return None + + monkeypatch.setattr(module_under_test, "find_open_port", mock_find_open_port) + mock_flow = mock.create_autospec(flow.InstalledAppFlow, instance=True) + + with mock.patch( + "google_auth_oauthlib.flow.InstalledAppFlow", autospec=True + ) as mock_flow, pytest.raises(ConnectionError): + mock_flow.from_client_config.return_value = mock_flow + module_under_test.get_user_credentials( + ["scopes"], "some-client-id", "shh-secret" + ) + + mock_flow.run_local_server.assert_not_called()