@@ -477,6 +477,52 @@ def test_retry_kwargs_threaded_into_kernel_client(self):
477477 finally :
478478 conn .close ()
479479
480+ def test_remapped_host_and_path_threaded_into_kernel_client (self ):
481+ """The remapped ``server_hostname``/``http_path`` from
482+ ``_kernel_host_and_path`` must reach ``KernelDatabricksClient``.
483+ Guards against a regression that dropped or reordered the call so
484+ the raw (pre-override) values leaked through — the silent-ignore
485+ bug this PR fixes, which the pure-function tests alone can't catch.
486+ """
487+ import sys
488+ import types
489+
490+ pytest .importorskip (
491+ "pyarrow" ,
492+ reason = "kernel client module imports pyarrow at load" ,
493+ )
494+
495+ fake = types .ModuleType ("databricks_sql_kernel" )
496+ fake .KernelError = type ("KernelError" , (Exception ,), {})
497+ fake .Session = MagicMock ()
498+
499+ with patch .dict (sys .modules , {"databricks_sql_kernel" : fake }), patch (
500+ "databricks.sql.backend.kernel.client.KernelDatabricksClient"
501+ ) as mock_kernel_client , patch (
502+ "%s.session.get_python_sql_connector_auth_provider" % self .PACKAGE
503+ ):
504+ instance = mock_kernel_client .return_value
505+ instance .open_session .return_value = SessionId (
506+ BackendType .SEA , "sess-id" , None
507+ )
508+
509+ conn = databricks .sql .connect (
510+ server_hostname = "foo.cloud.databricks.com" ,
511+ http_path = "/sql/1.0/warehouses/abc" ,
512+ use_kernel = True ,
513+ access_token = "dapi-xyz" ,
514+ enable_telemetry = False ,
515+ _connection_uri = "https://direct.example.com:8443/sql/1.0/warehouses/xyz" ,
516+ )
517+ try :
518+ _ , kwargs = mock_kernel_client .call_args
519+ # The _connection_uri override must be split and remapped
520+ # onto the kernel client, not passed through raw.
521+ assert kwargs ["server_hostname" ] == "https://direct.example.com:8443"
522+ assert kwargs ["http_path" ] == "/sql/1.0/warehouses/xyz"
523+ finally :
524+ conn .close ()
525+
480526
481527class TestKernelUserAgentForwarding :
482528 """user_agent_entry must reach the kernel on the use_kernel path —
@@ -527,6 +573,79 @@ def test_user_agent_entry_reaches_kernel_client_http_headers(self):
527573 conn .close ()
528574
529575
576+ class TestKernelSpogHeaderReDerivedFromResolvedPath :
577+ """On the kernel path a ``_connection_uri`` override can rewrite the
578+ http_path to a different workspace. The SPOG ``x-databricks-org-id``
579+ header is computed in ``__init__`` from the *original* http_path, so it
580+ must be re-derived from the resolved kernel path — otherwise the kernel
581+ would receive an org-id pointing at the pre-override workspace."""
582+
583+ PACKAGE = "databricks.sql"
584+
585+ def _connect_and_get_kernel_headers (self , connect_kwargs ):
586+ import sys
587+ import types
588+
589+ pytest .importorskip (
590+ "pyarrow" , reason = "kernel client module imports pyarrow at load"
591+ )
592+
593+ fake = types .ModuleType ("databricks_sql_kernel" )
594+ fake .KernelError = type ("KernelError" , (Exception ,), {})
595+ fake .Session = MagicMock ()
596+
597+ with patch .dict (sys .modules , {"databricks_sql_kernel" : fake }), patch (
598+ "databricks.sql.backend.kernel.client.KernelDatabricksClient"
599+ ) as mock_kernel_client , patch (
600+ "%s.session.get_python_sql_connector_auth_provider" % self .PACKAGE
601+ ):
602+ instance = mock_kernel_client .return_value
603+ instance .open_session .return_value = SessionId (
604+ BackendType .SEA , "sess-id" , None
605+ )
606+
607+ conn = databricks .sql .connect (
608+ server_hostname = "foo.cloud.databricks.com" ,
609+ use_kernel = True ,
610+ access_token = "dapi-xyz" ,
611+ enable_telemetry = False ,
612+ ** connect_kwargs ,
613+ )
614+ try :
615+ _ , kwargs = mock_kernel_client .call_args
616+ return dict (kwargs ["http_headers" ])
617+ finally :
618+ conn .close ()
619+
620+ def test_org_id_re_derived_from_connection_uri_override (self ):
621+ # Original path routes to workspace 111; the _connection_uri override
622+ # points at workspace 222 — the kernel must see org-id 222.
623+ headers = self ._connect_and_get_kernel_headers (
624+ {
625+ "http_path" : "/sql/1.0/warehouses/abc?o=111" ,
626+ "_connection_uri" : "https://direct.example.com/sql/1.0/warehouses/xyz?o=222" ,
627+ }
628+ )
629+ assert headers .get ("x-databricks-org-id" ) == "222"
630+
631+ def test_org_id_dropped_when_override_has_no_workspace (self ):
632+ # The override points at a path with no workspace routing info, so the
633+ # stale org-id (from the original path) must not be carried over.
634+ headers = self ._connect_and_get_kernel_headers (
635+ {
636+ "http_path" : "/sql/1.0/warehouses/abc?o=111" ,
637+ "_connection_uri" : "https://direct.example.com/sql/1.0/warehouses/xyz" ,
638+ }
639+ )
640+ assert "x-databricks-org-id" not in headers
641+
642+ def test_org_id_preserved_when_no_override (self ):
643+ headers = self ._connect_and_get_kernel_headers (
644+ {"http_path" : "/sql/1.0/warehouses/abc?o=111" }
645+ )
646+ assert headers .get ("x-databricks-org-id" ) == "111"
647+
648+
530649@pytest .mark .realkernel
531650class TestUseKernelRoutesThroughRealWheel :
532651 """No-network proof that ``sql.connect(use_kernel=True)`` actually
@@ -638,6 +757,11 @@ def test_connection_uri_wins_over_port(self):
638757 assert host == "https://direct.example.com:9999"
639758 assert path == "/p"
640759
760+ def test_connection_uri_without_authority_raises (self ):
761+ for bad in ("//no-scheme-authority" , "https:///only-path" ):
762+ with pytest .raises (ValueError , match = "could not determine host authority" ):
763+ _kernel_host_and_path (self .HOST , self .PATH , {"_connection_uri" : bad })
764+
641765 def test_port_folded_into_bare_host (self ):
642766 host , path = _kernel_host_and_path (self .HOST , self .PATH , {"_port" : 8443 })
643767 assert host == "{}:8443" .format (self .HOST )
@@ -646,3 +770,13 @@ def test_port_folded_into_bare_host(self):
646770 def test_port_not_double_appended_when_host_has_port (self ):
647771 host , _ = _kernel_host_and_path (self .HOST + ":7000" , self .PATH , {"_port" : 8443 })
648772 assert host == self .HOST + ":7000"
773+
774+ def test_port_folded_into_ipv6_literal_without_port (self ):
775+ # An IPv6 authority contains ``:`` even without a port, so a naive
776+ # ``":" in host`` check would wrongly skip appending _port.
777+ host , _ = _kernel_host_and_path ("[::1]" , self .PATH , {"_port" : 8443 })
778+ assert host == "[::1]:8443"
779+
780+ def test_port_not_double_appended_for_ipv6_literal_with_port (self ):
781+ host , _ = _kernel_host_and_path ("[::1]:7000" , self .PATH , {"_port" : 8443 })
782+ assert host == "[::1]:7000"
0 commit comments