@@ -251,8 +251,9 @@ class TestKernelOAuthU2M:
251251 The kernel core default U2M app is ``databricks-sql-connector`` /
252252 ``sql offline_access`` / port 8030 (see PECOBLR-4039). The Python
253253 connector is an OVERRIDE: on the kernel path it forwards its OWN
254- coupled ``client_id`` + ``redirect_port`` bundle so it authenticates
255- as ``databricks-sql-python`` rather than the kernel default. A caller
254+ coupled ``client_id`` + ``redirect_ports`` bundle (the full registered
255+ port list, for busy-port fallback) so it authenticates as
256+ ``databricks-sql-python`` rather than the kernel default. A caller
256257 may override ``oauth_scopes``; absent one, ``PYSQL_OAUTH_SCOPES`` is
257258 forwarded as the default.
258259
@@ -271,7 +272,8 @@ def test_bare_databricks_oauth_forwards_full_python_bundle(self):
271272 assert kwargs == {
272273 "auth_type" : "oauth-u2m" ,
273274 "client_id" : PYSQL_OAUTH_CLIENT_ID ,
274- "redirect_port" : PYSQL_OAUTH_REDIRECT_PORT_RANGE [0 ],
275+ # Full registered port list → the kernel binds the first free one.
276+ "redirect_ports" : list (PYSQL_OAUTH_REDIRECT_PORT_RANGE ),
275277 "oauth_scopes" : list (PYSQL_OAUTH_SCOPES ),
276278 }
277279
@@ -294,8 +296,9 @@ def test_azure_oauth_not_supported(self, opts):
294296 kernel_auth_kwargs (_FakeOAuthProvider (), opts )
295297
296298 def test_u2m_custom_client_id_port_and_scopes_honored (self ):
297- # A caller may override the coupled client_id + redirect_port and
298- # the oauth_scopes. All three are forwarded as supplied.
299+ # A caller may override the coupled client_id + redirect port and the
300+ # oauth_scopes. The single custom port is forwarded as a one-element
301+ # redirect_ports list; all three are forwarded as supplied.
299302 kwargs = kernel_auth_kwargs (
300303 _FakeOAuthProvider (),
301304 {
@@ -308,14 +311,14 @@ def test_u2m_custom_client_id_port_and_scopes_honored(self):
308311 assert kwargs == {
309312 "auth_type" : "oauth-u2m" ,
310313 "client_id" : "custom-client" ,
311- "redirect_port " : 9999 ,
314+ "redirect_ports " : [ 9999 ] ,
312315 "oauth_scopes" : ["custom-scope" , "offline_access" ],
313316 }
314317
315318 def test_u2m_custom_client_id_only_falls_back_to_connector_defaults (self ):
316319 # A custom client_id without explicit scopes/port fills the
317320 # remaining two from the connector defaults — a custom client_id
318- # still uses PYSQL_OAUTH_SCOPES and the default redirect-port range .
321+ # still uses PYSQL_OAUTH_SCOPES and the default redirect-port list .
319322 kwargs = kernel_auth_kwargs (
320323 _FakeOAuthProvider (),
321324 {
@@ -326,7 +329,7 @@ def test_u2m_custom_client_id_only_falls_back_to_connector_defaults(self):
326329 assert kwargs == {
327330 "auth_type" : "oauth-u2m" ,
328331 "client_id" : "custom-client" ,
329- "redirect_port " : PYSQL_OAUTH_REDIRECT_PORT_RANGE [ 0 ] ,
332+ "redirect_ports " : list ( PYSQL_OAUTH_REDIRECT_PORT_RANGE ) ,
330333 "oauth_scopes" : list (PYSQL_OAUTH_SCOPES ),
331334 }
332335
@@ -343,8 +346,8 @@ def test_u2m_redirect_port_coerced_to_int(self):
343346 "oauth_redirect_port" : "8021" ,
344347 },
345348 )
346- assert kwargs ["redirect_port " ] == 8021
347- assert isinstance (kwargs ["redirect_port" ], int )
349+ assert kwargs ["redirect_ports " ] == [ 8021 ]
350+ assert isinstance (kwargs ["redirect_ports" ][ 0 ], int )
348351
349352 def test_u2m_redirect_port_non_numeric_raises_programming_error (self ):
350353 # A garbled oauth_redirect_port is a caller error of the same class
@@ -362,18 +365,17 @@ def test_u2m_redirect_port_non_numeric_raises_programming_error(self):
362365 )
363366
364367 def test_u2m_redirect_port_ignored_without_client_id (self ):
365- # A bare oauth_redirect_port (no explicit client_id) must NOT be
366- # forwarded: it would be paired with the default databricks-sql-python
367- # app, whose registered redirect URIs only cover the default port
368- # range, so an arbitrary port would resolve to an unregistered URI
369- # and fail the U2M flow. This mirrors the Thrift path's coupling,
370- # where oauth_redirect_port_range is only overridden when both
368+ # A bare oauth_redirect_port (no explicit client_id) must NOT replace
369+ # the default list: it would be paired with the default
370+ # databricks-sql-python app, so we keep forwarding that app's full
371+ # registered port list. This mirrors the Thrift path's coupling, where
372+ # oauth_redirect_port_range is only overridden when both
371373 # oauth_client_id and oauth_redirect_port are supplied.
372374 kwargs = kernel_auth_kwargs (
373375 _FakeOAuthProvider (),
374376 {"auth_type" : "databricks-oauth" , "oauth_redirect_port" : 9999 },
375377 )
376- assert kwargs ["redirect_port " ] == PYSQL_OAUTH_REDIRECT_PORT_RANGE [ 0 ]
378+ assert kwargs ["redirect_ports " ] == list ( PYSQL_OAUTH_REDIRECT_PORT_RANGE )
377379
378380 def test_u2m_honors_custom_scopes (self ):
379381 # A caller-supplied oauth_scopes is forwarded to the kernel, even
0 commit comments