Skip to content

Commit 11fdf3f

Browse files
committed
tests: tighten test_runtime.py to match repo idioms
Use monkeypatch.setitem for the sys.modules injection (auto-teardown instead of manual save/restore), move the runtime reload into the fixture so test bodies stay focused on the assertion, inline the fake initializer, and strengthen the first assertion to isinstance( RemoteDbUtils) so it explicitly proves the Spark Connect fallback path was taken rather than just that some dbutils exists.
1 parent 61cc935 commit 11fdf3f

1 file changed

Lines changed: 36 additions & 59 deletions

File tree

tests/test_runtime.py

Lines changed: 36 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,61 @@
1-
"""Tests for the import-time behavior of the ``databricks.sdk.runtime`` package."""
1+
"""Tests for the import-time behavior of ``databricks.sdk.runtime``."""
22

33
import importlib
44
import sys
55
import types
66

77
import pytest
88

9+
from databricks.sdk.dbutils import RemoteDbUtils
910

10-
class _RemoteClientInitializer:
11-
"""Stand-in for ``dbruntime.UserNamespaceInitializer`` on a Spark Connect runtime.
1211

13-
On a shared-access-mode (Spark Connect) cluster, materializing the legacy user namespace
14-
builds a ``SparkContext``, which is unavailable in remote clients and raises
15-
``CONTEXT_UNAVAILABLE_FOR_REMOTE_CLIENT``.
16-
"""
17-
18-
@staticmethod
19-
def getOrCreate():
20-
class _Namespace:
21-
def get_namespace_globals(self):
22-
raise RuntimeError(
23-
"[CONTEXT_UNAVAILABLE_FOR_REMOTE_CLIENT] Calls to SparkContext are not "
24-
"supported on a Spark Connect cluster. Use spark instead."
25-
)
12+
@pytest.fixture
13+
def spark_connect_runtime(monkeypatch):
14+
"""``dbruntime`` is importable, but materializing the legacy user namespace raises
15+
``CONTEXT_UNAVAILABLE_FOR_REMOTE_CLIENT`` — the Spark Connect failure mode."""
2616

27-
return _Namespace()
17+
class _Initializer:
18+
@staticmethod
19+
def getOrCreate():
20+
class _Namespace:
21+
def get_namespace_globals(self):
22+
raise RuntimeError(
23+
"[CONTEXT_UNAVAILABLE_FOR_REMOTE_CLIENT] Calls to SparkContext are "
24+
"not supported on a Spark Connect cluster. Use spark instead."
25+
)
2826

27+
return _Namespace()
2928

30-
@pytest.fixture
31-
def spark_connect_runtime(monkeypatch):
32-
"""Simulate a Spark Connect runtime: ``dbruntime`` is importable, but materializing the
33-
legacy user namespace raises ``CONTEXT_UNAVAILABLE_FOR_REMOTE_CLIENT``."""
3429
fake = types.ModuleType("dbruntime")
35-
fake.UserNamespaceInitializer = _RemoteClientInitializer
36-
had_dbruntime = "dbruntime" in sys.modules
37-
saved_dbruntime = sys.modules.get("dbruntime")
38-
sys.modules["dbruntime"] = fake
39-
40-
# The remote fallback constructs ``RemoteDbUtils()``, which initializes a default ``Config``;
41-
# give it hermetic PAT credentials so the fallback itself doesn't fail for unrelated auth
42-
# reasons (see databricks-sdk-py#986).
30+
fake.UserNamespaceInitializer = _Initializer
31+
monkeypatch.setitem(sys.modules, "dbruntime", fake)
32+
33+
# The remote fallback constructs ``RemoteDbUtils()``, which initializes a default
34+
# ``Config``; hermetic PAT credentials keep the fallback from failing for unrelated
35+
# auth reasons (see databricks-sdk-py#986).
4336
monkeypatch.setenv("DATABRICKS_HOST", "https://test.cloud.databricks.com")
4437
monkeypatch.setenv("DATABRICKS_TOKEN", "test-token")
4538

46-
saved_runtime = sys.modules.get("databricks.sdk.runtime")
47-
try:
48-
yield
49-
finally:
50-
if had_dbruntime:
51-
sys.modules["dbruntime"] = saved_dbruntime
52-
else:
53-
sys.modules.pop("dbruntime", None)
54-
# Restore ``databricks.sdk.runtime`` to its pre-test state. If it was loaded before this
55-
# test, reload it cleanly while the PAT env is still set; otherwise drop it so it is
56-
# re-imported lazily on next use.
57-
if saved_runtime is None:
58-
sys.modules.pop("databricks.sdk.runtime", None)
59-
else:
60-
importlib.reload(saved_runtime)
61-
62-
63-
def test_runtime_import_survives_spark_connect_remote_client(spark_connect_runtime):
64-
"""Regression for dbt-databricks#1252: importing ``databricks.sdk.runtime`` on a Spark
65-
Connect runtime must fall back to the remote implementation instead of raising."""
66-
import databricks.sdk.runtime as runtime
39+
# Re-execute ``databricks.sdk.runtime``'s module body with the fake ``dbruntime`` in
40+
# place, then restore on teardown by reloading once more without it.
41+
import databricks.sdk.runtime
6742

68-
importlib.reload(runtime) # re-execute the module body with the faked ``dbruntime`` present
69-
70-
assert runtime.is_local_implementation is True
71-
assert runtime.dbutils is not None
43+
importlib.reload(databricks.sdk.runtime)
44+
yield
45+
importlib.reload(databricks.sdk.runtime)
7246

7347

74-
def test_workspace_client_constructs_on_spark_connect(spark_connect_runtime, config):
75-
"""End-to-end: constructing a ``WorkspaceClient`` on a Spark Connect runtime must not raise
76-
``CONTEXT_UNAVAILABLE_FOR_REMOTE_CLIENT`` (the actual dbt-databricks#1252 failure, since
77-
``WorkspaceClient.__init__`` eagerly builds dbutils via ``databricks.sdk.runtime``)."""
48+
def test_runtime_import_falls_back_on_spark_connect(spark_connect_runtime):
49+
"""Regression for dbt-databricks#1252: import survives the namespace failure."""
7850
import databricks.sdk.runtime as runtime
7951

80-
importlib.reload(runtime)
52+
assert runtime.is_local_implementation is True
53+
assert isinstance(runtime.dbutils, RemoteDbUtils)
54+
8155

56+
def test_workspace_client_constructs_on_spark_connect(spark_connect_runtime, config):
57+
"""Regression for dbt-databricks#1252: ``WorkspaceClient.__init__`` eagerly builds
58+
dbutils via ``databricks.sdk.runtime`` and must not raise on Spark Connect."""
8259
from databricks.sdk import WorkspaceClient
8360

8461
ws = WorkspaceClient(config=config)

0 commit comments

Comments
 (0)