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()

Reply via email to