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 2026-09-04 12:38:18
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-google-auth-oauthlib (Old)
and /work/SRC/openSUSE:Factory/.python-google-auth-oauthlib.new.1265 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-google-auth-oauthlib"
Fri Sep 4 12:38:18 2026 rev:25 rq:1375645 version:1.4.1
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-google-auth-oauthlib/python-google-auth-oauthlib.changes
2026-05-11 17:09:45.319435851 +0200
+++
/work/SRC/openSUSE:Factory/.python-google-auth-oauthlib.new.1265/python-google-auth-oauthlib.changes
2026-09-04 12:38:51.489313937 +0200
@@ -1,0 +2,7 @@
+Thu Sep 3 09:30:06 UTC 2026 - John Paul Adrian Glaubitz
<[email protected]>
+
+- Update to 1.4.1
+ * **google-auth-oauthlib:** prevent port re-use on windows (#18166)
+ * **handwritten:** centralize CONTRIBUTING.rst pointers (#17642)
+
+-------------------------------------------------------------------
Old:
----
google_auth_oauthlib-1.4.0.tar.gz
New:
----
google_auth_oauthlib-1.4.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-google-auth-oauthlib.spec ++++++
--- /var/tmp/diff_new_pack.aIeoCl/_old 2026-09-04 12:38:52.110335753 +0200
+++ /var/tmp/diff_new_pack.aIeoCl/_new 2026-09-04 12:38:52.112335823 +0200
@@ -18,7 +18,7 @@
%{?sle15_python_module_pythons}
Name: python-google-auth-oauthlib
-Version: 1.4.0
+Version: 1.4.1
Release: 0
Summary: Google authentication library
License: Apache-2.0
++++++ google_auth_oauthlib-1.4.0.tar.gz -> google_auth_oauthlib-1.4.1.tar.gz
++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google_auth_oauthlib-1.4.0/PKG-INFO
new/google_auth_oauthlib-1.4.1/PKG-INFO
--- old/google_auth_oauthlib-1.4.0/PKG-INFO 2026-05-07 09:10:53.690374900
+0200
+++ new/google_auth_oauthlib-1.4.1/PKG-INFO 2026-08-24 23:26:12.335985400
+0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: google-auth-oauthlib
-Version: 1.4.0
+Version: 1.4.1
Summary: Google Authentication Library
Home-page:
https://github.com/googleapis/google-cloud-python/tree/main/packages/google-auth-oauthlib
Author: Google Cloud Platform
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google_auth_oauthlib-1.4.0/google_auth_oauthlib/flow.py
new/google_auth_oauthlib-1.4.1/google_auth_oauthlib/flow.py
--- old/google_auth_oauthlib-1.4.0/google_auth_oauthlib/flow.py 2026-05-07
09:09:09.000000000 +0200
+++ new/google_auth_oauthlib-1.4.1/google_auth_oauthlib/flow.py 2026-08-24
23:22:35.128714800 +0200
@@ -58,7 +58,9 @@
except ImportError: # pragma: NO COVER
from random import SystemRandom
+import socket
from string import ascii_letters, digits
+import sys
import webbrowser
import wsgiref.simple_server
import wsgiref.util
@@ -432,10 +434,14 @@
authorization server.
"""
wsgi_app = _RedirectWSGIApp(success_message)
- # Fail fast if the address is occupied
- wsgiref.simple_server.WSGIServer.allow_reuse_address = False
+ # Use _ExclusiveWSGIServer to fail fast if the address/port is
occupied,
+ # and to prevent other apps from binding to it on Windows.
local_server = wsgiref.simple_server.make_server(
- bind_addr or host, port, wsgi_app,
handler_class=_WSGIRequestHandler
+ bind_addr or host,
+ port,
+ wsgi_app,
+ server_class=_ExclusiveWSGIServer,
+ handler_class=_WSGIRequestHandler,
)
try:
@@ -478,6 +484,23 @@
return self.credentials
+class _ExclusiveWSGIServer(wsgiref.simple_server.WSGIServer):
+ """Custom WSGIServer.
+
+ Enforces exclusive address binding on Windows.
+ Setting `WSGIServer.allow_reuse_address` is not enough, since it sets
`SO_REUSEADDR`
+ and not `SO_EXCLUSIVEADDRUSE`. `SO_REUSEADDR` alone allows other processes
to bind
+ to the same address and port on Windows.
+ """
+
+ allow_reuse_address = False
+
+ def server_bind(self):
+ if sys.platform == "win32" and hasattr(socket, "SO_EXCLUSIVEADDRUSE"):
+ self.socket.setsockopt(socket.SOL_SOCKET,
socket.SO_EXCLUSIVEADDRUSE, 1)
+ super().server_bind()
+
+
class _WSGIRequestHandler(wsgiref.simple_server.WSGIRequestHandler):
"""Custom WSGIRequestHandler.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/google_auth_oauthlib-1.4.0/google_auth_oauthlib.egg-info/PKG-INFO
new/google_auth_oauthlib-1.4.1/google_auth_oauthlib.egg-info/PKG-INFO
--- old/google_auth_oauthlib-1.4.0/google_auth_oauthlib.egg-info/PKG-INFO
2026-05-07 09:10:53.000000000 +0200
+++ new/google_auth_oauthlib-1.4.1/google_auth_oauthlib.egg-info/PKG-INFO
2026-08-24 23:26:12.317807400 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.4
Name: google-auth-oauthlib
-Version: 1.4.0
+Version: 1.4.1
Summary: Google Authentication Library
Home-page:
https://github.com/googleapis/google-cloud-python/tree/main/packages/google-auth-oauthlib
Author: Google Cloud Platform
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google_auth_oauthlib-1.4.0/setup.py
new/google_auth_oauthlib-1.4.1/setup.py
--- old/google_auth_oauthlib-1.4.0/setup.py 2026-05-07 09:09:10.000000000
+0200
+++ new/google_auth_oauthlib-1.4.1/setup.py 2026-08-24 23:22:32.498689400
+0200
@@ -30,7 +30,7 @@
long_description = fh.read()
-version = "1.4.0"
+version = "1.4.1"
setup(
name="google-auth-oauthlib",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/google_auth_oauthlib-1.4.0/tests/unit/test_flow.py
new/google_auth_oauthlib-1.4.1/tests/unit/test_flow.py
--- old/google_auth_oauthlib-1.4.0/tests/unit/test_flow.py 2026-05-07
09:09:10.000000000 +0200
+++ new/google_auth_oauthlib-1.4.1/tests/unit/test_flow.py 2026-08-24
23:22:33.550699500 +0200
@@ -20,9 +20,11 @@
import os
import re
import socket
+import time
from unittest import mock
import urllib
import webbrowser
+import wsgiref.simple_server
import pytest
import requests
@@ -444,10 +446,56 @@
self, webbrowser_mock, instance, mock_fetch_token, port, socket
):
# socket fixture is already bound to http://localhost:port
- instance.run_local_server
- with pytest.raises(OSError) as exc:
- instance.run_local_server(port=port)
- assert "address already in use" in exc.strerror.lower()
+ with pytest.raises(OSError):
+ instance.run_local_server(port=port, timeout_seconds=1)
+
+ @pytest.mark.webtest
+ @mock.patch("google_auth_oauthlib.flow.webbrowser", autospec=True)
+ def test_run_local_server_exclusive_port(
+ self, webbrowser_mock, instance, mock_fetch_token, port
+ ):
+ """Verify that while run_local_server is running, another socket
cannot bind to its port."""
+ auth_redirect_url = urllib.parse.urljoin(
+ f"http://localhost:{port}", self.REDIRECT_REQUEST_PATH
+ )
+
+ with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
+ future = pool.submit(partial(instance.run_local_server, port=port))
+ time.sleep(0.2)
+
+ hijack_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ hijack_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
+ try:
+ with pytest.raises(OSError):
+ hijack_socket.bind(("localhost", port))
+ finally:
+ hijack_socket.close()
+ while not future.done():
+ try:
+ requests.get(auth_redirect_url)
+ except requests.ConnectionError: # pragma: NO COVER
+ pass
+
+ credentials = future.result()
+
+ assert credentials.token == mock.sentinel.access_token
+
+ @mock.patch("google_auth_oauthlib.flow.webbrowser", autospec=True)
+ @mock.patch("wsgiref.simple_server.make_server", autospec=True)
+ def test_run_local_server_uses_exclusive_server_class(
+ self, make_server_mock, webbrowser_mock, instance
+ ):
+ server_mock = mock.MagicMock()
+ make_server_mock.return_value = server_mock
+
+ with pytest.raises(Exception):
+ instance.run_local_server(port=0)
+
+ make_server_mock.assert_called_once()
+ assert (
+ make_server_mock.call_args.kwargs.get("server_class")
+ is flow._ExclusiveWSGIServer
+ )
@mock.patch("google_auth_oauthlib.flow.webbrowser.get", autospec=True)
@mock.patch("wsgiref.simple_server.make_server", autospec=True)
@@ -514,3 +562,34 @@
webbrowser_mock.get.assert_called_with(None)
webbrowser_mock.get.return_value.open.assert_called_once()
+
+
+class TestExclusiveWSGIServer(object):
+ def test_exclusive_wsgi_server_bind_windows(self):
+ with mock.patch("sys.platform", "win32"), mock.patch(
+ "google_auth_oauthlib.flow.socket"
+ ) as mock_socket:
+ mock_socket.SOL_SOCKET = socket.SOL_SOCKET
+ mock_socket.SO_EXCLUSIVEADDRUSE = getattr(socket,
"SO_EXCLUSIVEADDRUSE", 1)
+
+ server = flow._ExclusiveWSGIServer(
+ ("localhost", 0), flow._WSGIRequestHandler,
bind_and_activate=False
+ )
+ server.socket = mock.Mock()
+
+ with mock.patch.object(wsgiref.simple_server.WSGIServer,
"server_bind"):
+ server.server_bind()
+ server.socket.setsockopt.assert_called_once_with(
+ mock_socket.SOL_SOCKET, mock_socket.SO_EXCLUSIVEADDRUSE, 1
+ )
+
+ def test_exclusive_wsgi_server_bind_non_windows(self):
+ with mock.patch("sys.platform", "linux"):
+ server = flow._ExclusiveWSGIServer(
+ ("localhost", 0), flow._WSGIRequestHandler,
bind_and_activate=False
+ )
+ server.socket = mock.Mock()
+
+ with mock.patch.object(wsgiref.simple_server.WSGIServer,
"server_bind"):
+ server.server_bind()
+ server.socket.setsockopt.assert_not_called()